从零写分布式RPC框架 系列 第一版 (1)架构设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/alinyua/article/details/83757901

本系列文章的目的是搭建出一个基于Netty,Zookeeper和SpringBoot的简易分布式RPC框架,并且发布到Maven中央仓库以 spring-boot-starter 的形式对外提供开箱即用的服务。1.0 版本使用 protobuf 来做序列化,最终的使用形式比较接近于 Dubbo 。最终效果可见:https://github.com/linshenkx/rpc-netty-spring-boot-starter

一 RPC设计

如下图,本RPC框架主要有Registry、RPC Server 和 RPC Client 3个角色。

  • Registry
    注册中心,底层实现是Zookeeper,可借助ZK集群达到服务的高可用
  • RPC Server
    RPC服务器,即服务提供方,通过自定义的协议而非http接口对外提供服务实现
    需要向Registry注册服务信息和自身信息
  • RPC Client
    RPC客户端,即服务消费者,通过向Registry订阅服务,获取提供对应服务实现的RPC Server信息,从而通过自定义协议从RPC Server获取服务实现。

注意:本框架1.0版本未完善 RPC Client 和 Registry 的发布订阅模型,所以每次都需要 RPC Client去 Registry 获取信息再 向 RPC Server 发起服务调用,也由此带来极大的性能损耗和浪费。1.0版本只是实现了一个框架原型,后续版本将对性能等做优化。

设计

二 模块结构

结构图如下,其中 examples 模块不依赖于父工程,可独立运行,不属于框架的一部分。
结构图
rpc-netty-spring-boot-starter 下有5个模块,其中外部使用的是两个 starter ,而真正工作的事另外三个模块。

  • rpc-netty-common
    封装统一规则,如使RPC Server和RPC Client 可以基于同一协议通信。
    内含 自定义RPC通信对象及序列化方法,还有对应的Netty编码器、解码器等。
  • rpc-netty-server-spring-boot-autoconfigure
    • 核心类是RpcServer,负责提供RPC服务
    • 内含 ZKServiceRegistry 负责向zk集群注册服务,@RpcService 注解对外提供使用
    • 另外还有 RpcServerHandler 提供Netty 通信处理,ZKProperties 和 RpcServerProperties 提供属性注入。
  • rpc-netty-server-spring-boot-starter
    对 rpc-netty-server-spring-boot-autoconfigure 进行包装,本身无功能实现
  • rpc-netty-client-spring-boot-autoconfigure
    • 核心类是RpcClient,负责获取服务实现生成代理类
    • 内含 ZKServiceDiscovery 负责发现指定服务的RPC Server信息
    • 另外还有 RpcClientHandler 提供Netty 通信处理,ZKProperties 提供属性注入。
  • rpc-netty-client-spring-boot-starter
    对rpc-netty-client-spring-boot-autoconfigure 进行包装,本身无功能实现

三 工作流程

RPC Server

服务启动
扫描 RpcService 注解类
收集能实现的服务
在RpcServerProperties指定端口上 启动Netty服务器
向zk集群注册服务和自身信息

需要注意,RPC Server需一直维持与zk集群的连接,如果关闭RPC Server,zk上注册的信息会随之清除。

RPC Client

服务端利用反射执行方法生成结果
用户触发
获取服务实现
传递接口信息
服务端返回结果

需要注意,这里没有使用发布订阅模型,没有维持连接,所以每次使用都需要去获取服务实现,没有使用池化技术和缓存。需要在后续版本改良。

四 功能依赖

  • rpc-netty-common 模块
    • protostuff-core :Rptostuff 核心模块,提供对象序列化和反序列化功能
    • protostuff-runtime:Protostuff 运行时模块,用于生成所需的 Protostuff Schema 对象
    • objenesis:提供比 JDK 更高效的反射功能,用于对象反序列化
  • rpc-netty-server-spring-boot-autoconfigure 和 rpc-netty-server-spring-boot-autoconfigure 模块
    • spring-boot-starter:提供spring-boot 基础服务,如 spring-context 信息等,该依赖scope 应为 provided ,由使用方提供依赖,避免版本冲突
    • spring-boot-configuration-processor:提供属性注入,scope同上
    • rpc-netty-common:提供统一服务
    • zkclient :提供对zk集群的操作,注意应使用 exclusion 将其 slf4j-log4j12 模块排除在classpath,否则会与spring-boot日志框架重复或与Lombok的@log4j2冲突

除了上述依赖,还有以上3个模块都依赖的

  • netty-all :Netty模块,提供NIO通信所需的API,是整个RPC框架的基础
  • lombok:其 optional 应为true ,避免传递依赖

另外,两个spring-boot-starter分别只依赖各自的spring-boot-autoconfigure模块

注意,为了避免依赖冲突问题,这里使用到了 scope设为provided,exclusion排除模块, optional设为true 三种方法。详情请见:provided,optional 和 exclusion 最全区分指南

  1. scope设为provided:对依赖整体有效,依赖将提供编译而不参与打包,由使用方提供
    在本项目中,则是在发布后,由使用 spring-boot-starter 的spring-boot工程提供。
  2. exclusion排除特定组件:避免传递依赖
    本项目中,用于移去 zkclient 的 slf4j-log4j12 模块,避免依赖导入
  3. optional设为true:避免传递依赖
    本项目中,rpc-netty-server-spring-boot-autoconfigure依赖optional为true的 Lombok ,但 rpc-netty-server-spring-boot-starter则不含 Lombok 模块,避免依赖传出

五 父工程pom

这里我把部署到maven 中央仓库的内容删去,不影响正常使用,感兴趣的可以到GitHub找完整项目查看,部署的中央仓库的方法见:使用gpg插件发布jar包到Maven中央仓库 完整实践

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.linshenkx</groupId>
    <artifactId>rpc-netty-spring-boot-starter</artifactId>
    <version>1.0.5.RELEASE</version>
    <packaging>pom</packaging>

    <name>rpc-netty-spring-boot-starter</name>
    <description>基于Netty的简易RPC框架</description>
    <url>https://github.com/linshenkx/rpc-netty-spring-boot-starter</url>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.0.RELEASE</spring-boot.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
        <netty.version>4.1.31.Final</netty.version>
        <protostuff.version>1.5.9</protostuff.version>
        <objenesis.version>3.0.1</objenesis.version>
        <zkclient.version>0.11</zkclient.version>
    </properties>

    <modules>
        <module>rpc-netty-common</module>
        <module>rpc-netty-server-spring-boot-autoconfigure</module>
        <module>rpc-netty-server-spring-boot-starter</module>
        <module>rpc-netty-client-spring-boot-autoconfigure</module>
        <module>rpc-netty-client-spring-boot-starter</module>
    </modules>
   
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>${spring-boot.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <version>${spring-boot.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.github.linshenkx</groupId>
                <artifactId>rpc-netty-common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.linshenkx</groupId>
                <artifactId>rpc-netty-server-spring-boot-autoconfigure</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.linshenkx</groupId>
                <artifactId>rpc-netty-client-spring-boot-autoconfigure</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>${netty.version}</version>
            </dependency>
            <dependency>
                <groupId>io.protostuff</groupId>
                <artifactId>protostuff-core</artifactId>
                <version>${protostuff.version}</version>
            </dependency>
            <dependency>
                <groupId>io.protostuff</groupId>
                <artifactId>protostuff-runtime</artifactId>
                <version>${protostuff.version}</version>
            </dependency>
            <dependency>
                <groupId>org.objenesis</groupId>
                <artifactId>objenesis</artifactId>
                <version>${objenesis.version}</version>
            </dependency>
            <dependency>
                <groupId>com.101tec</groupId>
                <artifactId>zkclient</artifactId>
                <version>${zkclient.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-log4j12</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
</project>

其他

参考资料:
项目GitHub主页:https://github.com/linshenkx/rpc-netty-spring-boot-starter
《架构探险 轻量级微服务架构 下册》黄勇 著,第四章-微服务通信
Dubbo GitHub主页:https://github.com/apache/incubator-dubbo
https://github.com/luxiaoxun/NettyRpc
https://github.com/yidongnan/grpc-spring-boot-starter

猜你喜欢

转载自blog.csdn.net/alinyua/article/details/83757901
今日推荐