Home > Common Problem > The handwritten RPC framework is really not just for pretending to be 13!

The handwritten RPC framework is really not just for pretending to be 13!

Release: 2023-08-16 17:01:18
forward
767 people have browsed it

During the interview, it is easy to be asked by the interviewer:

How to design an RPC framework?

You may not have been asked, maybe you are lucky, or maybe you are not at this level yet. Usually the monthly salary is more than 20k, and they will basically ask some design questions.

From the interviewer’s perspective: Asking this type of question is better than an eight-part essay, which involves many technical points. For example: knowledge about design patterns, communication protocols, dynamic agents, virtualization, thread pools, etc.

Okay, let’s not go too far, let’s start talking about today’s topic.

RPC is a Remote procedure call. Many people may not particularly understand these words. To put it simply:

It’s like calling a local The method is the same as calling the remote service.

For example, the following case: a user operates a service:

public interface UserService{
    String findUserNameById(Integer userId);
}
@Service
public class UserServiceImpl implements UserService{
    String findUserNameById(Integer userId){
        //查数据或查缓存获取到用户名
        return "田哥"
    }
}
Copy after login

Now a controller wants to call the findUserNameById method of UserServiceImpl to obtain the user name.

@RestController
public class UserController{
    @Resource
    private UserService userService;
    
    @GetMapping("/test")
    public String test(){
        return userService.findUserNameById(1);
    }
}
Copy after login

Assuming that the three classes UserController, UserServiceImpl, and UserService are all in the same project, it is very simple for the controller to call the findUserNameById method.

However, if the controller is another project and wants to be called as above (subtle difference, the feeling is still the same), then we can use the RPC framework.

1. The interface UserService needs to be placed in a separate project, which we usually call an api project.

2. UserServiceImpl needs to be placed in a separate project, which we usually call the provider project.

3. Controller, through a web or other (consumer) project

4. Type the API into a jar package, and then reference it in both the consumer project and the provider project.

The RPC frameworks on the market, such as: Dubbo (Alibaba), Thrift (FaceBook), gRpc (Google), brpc (Baidu), etc., all focus on different aspects to solve the original purpose. Some want extreme perfection, some pursue extreme performance, and some prefer extreme simplicity.

RPC Principle

Back to what we said earlierCalling remote services like calling local services, what technical support is needed?

  • Dynamic proxy, because our consumer project only has the interface UserService defined and no implementation class. Do you want to call a method of the interface? Then you can only create a proxy object.
  • Encoding, that is, the consumer needs to pass the request parameters to the provider. The network transmission process first encodes our parameters and then passes them to the provider. The provider then decodes the passed parameters.
  • Network communication, cross-process will definitely involve network communication.
  • Network transmission protocol, consumer and provider must have a standard for the parameter information going back and forth. How do you pass it to me? Otherwise I How do you know what you want to express.
  • Serialization and deserialization
  • Data compression, during data network transmission, if the data is too large , we have to consider whether the data can be compressed.
  • Registration Center, if the provider performs cluster deployment (the same service is deployed on multiple machines), then we need to perform manual maintenance on the consumer. If the volume is large Get up, the workload can be imagined.
  • Dynamic awareness of service online and offline, if the provider is down or a new node is deployed, then the consumer needs to know which services are offline and which services On the line.
  • Dynamic routing, if the provider is deployed in a cluster (the same service is deployed on multiple machines), we cannot have all consumers fall on the same node, so Resources cannot be fully utilized, and the ancient emperor's rain and dew are all stained . Dynamic routing involves a variety of algorithms, such as randomization, polling, weighting, etc.

Why is a registration center needed? I have shared it before:

Meituan Interview: How to design a registration center?

造轮子

根据上面的这些原理,田哥也搞了一个RPC框架,命名为mink(一个动物的名称)。

--mink
----mink-rpc rpc基本功能
----mink-registry 服务注册与发现
----mink-spring 集成SpringBoot
Copy after login

然后,我们把mink-spring打成jar包,服务发布和服务引用都把这个jar给依赖进去。

The handwritten RPC framework is really not just for pretending to be 13!

The handwritten RPC framework is really not just for pretending to be 13!

The handwritten RPC framework is really not just for pretending to be 13!


框架使用

上面,我们创造了轮子,下面,我们就来看如何使用。

The handwritten RPC framework is really not just for pretending to be 13!

mink-demo就是一个Spring Boot项目,有三个module。

The handwritten RPC framework is really not just for pretending to be 13!


我们把mink-api打成jar包,共consumer和provider使用。

也就是我们在consumer和provider都引入:

<dependency>
    <groupId>com.tian</groupId>
    <artifactId>mink-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
Copy after login

下面,我们来看看provider端的代码:

<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-spring</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-api</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <version>2.5.4</version>
</dependency>
Copy after login

我们的mink框架,只需要引入mink-spring依赖即可。

接着就是properties的配置:

mink.rpc.servicePort=20880
mink.rpc.registryType=0
mink.rpc.registryAddress=127.0.0.1:2181
Copy after login

再来看看具体服务实现类:

package com.tian.service;

import com.tian.annotation.MinkService;

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @description 用户服务
 * @createTime 2022年08月23日 18:16
 */
@MinkService
public class UserServiceImpl implements UserService {
    @Override
    public String findUserNameByiD(Integer id) {
        System.out.println("服务调用");
        return "tian";
    }
}
Copy after login

这一步,我们只需要在实现类上加上注解@MinkService即可。

最后就是项目启动类:

@ComponentScan(basePackages = {"com.tian.service","com.tian"})
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Copy after login

我们启动项目(注册中心用的是zookeeper):

The handwritten RPC framework is really not just for pretending to be 13!


从日志中可以看出,我们的服务已经成功注册到注册中心了。

下面,我们来看看consumer端代码。

首先来看看依赖:

<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-spring</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-api</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <version>2.5.4</version>
</dependency>

   org.springframework.boot
   spring-boot-starter-web
   2.5.4
Copy after login

这依赖也很简单,没什么好说的。

再来看看properties配置项:

mink.rpc.registryType=0
mink.rpc.registryAddress=127.0.0.1:2181

server.port=8090
Copy after login

是不是也很简单?

再来看看我们的controller代码:

package com.tian.controller;

import com.tian.annotation.MinkReference;
import com.tian.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @description 消费端
 * @createTime 2022年08月23日 23:08
 */
@RestController
public class UserController {

    @MinkReference
    private UserService userService;

    @RequestMapping("/test")
    public String test() {
        return userService.findUserNameByiD(1);
    }
}
Copy after login

需要用到对应服务,只需要添加注解@MinkReference即可。

最后就是项目启动类,简单的不行。

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Copy after login

启动日志:

The handwritten RPC framework is really not just for pretending to be 13!

访问:http://localhost:8090/test

The handwritten RPC framework is really not just for pretending to be 13!

成功!整个过程,非常轻松地集成mink框架并在业务代码中使用。

总结起来,其实就三步:

1、pom中添加依赖

2、properties文件中配置注册中心信息

3、使用的时候加上注解@MinkReference@MinkService即可

The above is the detailed content of The handwritten RPC framework is really not just for pretending to be 13!. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:Java后端技术全栈
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template