手把手教你撸一个RPC框架

什么是RPC调用

在动手之前,首先要明确rpc调用的概念,RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,简单来说就是无感知的调用远程服务的方法

举个例子,如果在A服务中实现了接口addCount(),进行计数+1,而B服务想调用A服务的这个接口,本地只需要通过函数指针来调用即可,而在两个服务中的调用就可以成为rpc调用

实现RPC调用的流程

生产者

  1. 扫描所有的提供服务的Service并对应的注册到注册中心中,暴露服务出去,并且在本地根据服务名称缓存服务执行对象。
  2. 开启本地服务接受消费者请求。
  3. 在接收到请求后根据服务名称寻找对应的执行对象,并通过反射的方式调用对应的方法。
  4. 将执行结果返回给消费者

消费者

  1. 对含有相应注解的字段注入代理对象。实现类似@Autowired的功能
  2. 将调用的类名,方法,参数,封装成元数据,并从注册中心获取对应执行地址
  3. 向执行地址发送相应数据,并接受返回结果

总体来说一个完整的RPC调用流程基本上如上所述,接下来我们就来实现一个简易的RPC调用框架,当然是基于java的,在理论上rpc调用是不限语言的,比如gRPC或者Thrift都是可以跨语言执行的,而当当网二次开发的Dubbox也是可以跨语言的。

工具选型

通过上述流程可以得知,在这个rpc框架中我们需要选择一个注册中心以及网络通讯框架,并且要选择通讯协议,在这个框架中我选择zookeeper做为注册中心,netty为网络通讯框架,通讯协议选择Http(别问,问就是好写)序列化协议选择JSON(别问,好写)。

项目创建

image-20200812150237339

整项目结构如上图,common项目是通用的内容也就是框架的主题内容,consumer是消费者项目,producer是生产者项目,这两个项目都是springboot项目并且依赖common项目。

通用部分

在common项目pom.xml中加入以下依赖

 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>

        </dependency>
        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.42.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
  <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.0.5</version>
        </dependency>

在common下创建config包,并创建RpcConfig类

@Component
@ConfigurationProperties(prefix = "myrpc")
public class RpcConfig {
   

    private String localAddress;

    private Integer  nettyPort;
  
    private String  basePackage;

    public String getBasePackage() {
   
        return basePackage;
    }

    public void setBasePackage(String basePackage) {
   
        this.basePackage = basePackage;
    }

    public Integer getNettyPort() {
   
        return nettyPort;
    }

    public void setNettyPort(Integer nettyPort) {
   
        this.nettyPort = nettyPort;
    }

    public String getLocalAddress() {
   
        return localAddress;
    }

    public void setLocalAddress(String localAddress) {
   
        this.localAddress = localAddress;
    }
}

该配置类配置本地请求地址以及netty启动对应端口

然后创建ZookeeperConfig类。

@Component
@ConfigurationProperties(prefix = "myrpc.zookeeper")
public class ZookeeperConfig {
   

    private String url;

    private Integer sessionTimeOut;

    public Integer getSessionTimeOut() {
   
        return sessionTimeOut;
    }

    public void setSessionTimeOut(Integer sessionTimeOut) {
   
        this.sessionTimeOut = sessionTimeOut;
    }

    public String getUrl() {
   
        return url;
    }

    public void setUrl(String url) {
   
        this.url = url;
    }


}

该类用于获取zookeeper相关的配置,然后在创建zookeeperRegister类,该类为zookeeper操作相关工具类

@Component
public class ZookeeperRegister {
   
		//根节点
    public static final String BASE_NODE = "/myrpc/";
    //缓存生产者数据
    public static ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<>();

    @Autowired
    private ZookeeperConfig zookeeperConfig;

    private ZooKeeper zooKeeper = null;
  
		//获取生产者信息
    public List<String> getProducer(Class<?> injectedType) throws Exception {
   
        List<String> producerList = map.get(injectedType.getTypeName());
       
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值