Heim >häufiges Problem >Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

Java后端技术全栈
Java后端技术全栈nach vorne
2023-08-16 17:01:18852Durchsuche

Im Interview wird der Interviewer leicht gefragt:

Wie entwerfe ich ein RPC-Framework?

Vielleicht wurdest du nicht gefragt, vielleicht hast du Glück, oder vielleicht bist du noch nicht auf diesem Niveau. Normalerweise beträgt das Monatsgehalt mehr als 20.000 und sie stellen grundsätzlich einige Designfragen.

Aus Sicht des Interviewers: Diese Art von Frage zu stellen ist besser als einen achtteiligen Aufsatz zu stellen, der viele technische Punkte beinhaltet. Zum Beispiel: Kenntnisse über Entwurfsmuster, Kommunikationsprotokolle, dynamische Agenten, Virtualisierung, Thread-Pools usw.

Okay, gehen wir nicht zu weit, fangen wir an, über das heutige Thema zu reden.

RPC ist ein Remote-Prozeduraufruf. Viele Leute verstehen diese Worte möglicherweise nicht besonders:

Rufen Sie einen Remote-Dienst auf, genau wie den Aufruf einer lokalen Methode.

Zum Beispiel der folgende Fall: Ein Benutzer betreibt einen Dienst:

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

Jetzt möchte ein Controller die findUserNameById-Methode von UserServiceImpl aufrufen, um den Benutzernamen zu erhalten.

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

Unter der Annahme, dass sich die drei Klassen UserController, UserServiceImpl und UserService alle im selben Projekt befinden, ist es für den Controller sehr einfach, die Methode findUserNameById aufzurufen.

Wenn der Controller jedoch ein anderes Projekt ist und wie oben aufgerufen werden möchte (feiner Unterschied, das Gefühl ist immer noch das gleiche), dann können wir das RPC-Framework verwenden.

1. Die Schnittstelle UserService muss in einem separaten Projekt platziert werden, das wir normalerweise als API-Projekt bezeichnen.

2. UserServiceImpl muss in einem separaten Projekt platziert werden, das wir normalerweise als Provider-Projekt bezeichnen.

3. Controller, durch Web- und andere (Verbraucher-)Projekte

4. Geben Sie die API in ein JAR-Paket ein und verweisen Sie dann sowohl im Verbraucherprojekt als auch im Anbieterprojekt darauf.

Die auf dem Markt erhältlichen RPC-Frameworks wie Dubbo (Alibaba), Thrift (FaceBook), gRpc (Google), brpc (Baidu) usw. konzentrieren sich alle auf unterschiedliche Aspekte, um den ursprünglichen Zweck zu lösen Seien Sie extrem perfekt, und manche wollen Perfektion erreichen, während andere extreme Einfachheit bevorzugen.

RPC-Prinzip

Zurück zu dem, was wir zuvor gesagt habenRufen Sie einen Remote-Dienst wie einen Ortsgespräch an, welche technische Unterstützung wird benötigt?

  • Dynamischer Proxy, da unser Verbraucherprojekt nur Schnittstellendefinitionen UserService und keine Implementierungsklassen hat. Möchten Sie eine Methode einer Schnittstelle aufrufen? Dann können Sie nur ein Proxy-Objekt erstellen.
  • Encoding, das heißt, der Verbraucher muss die Anforderungsparameter an den Anbieter übergeben. Der Netzwerkübertragungsprozess codiert zunächst unsere Parameter und übergibt sie dann an den Anbieter.
  • Netzwerkkommunikation, prozessübergreifend wird definitiv Netzwerkkommunikation beinhalten.
  • Netzwerkübertragungsprotokoll, Verbraucher und Anbieter Es muss einen Standard für die hin- und hergehenden Parameterinformationen geben. Wie kann ich sonst wissen, was Sie ausdrücken möchten?
  • Serialisierung und Deserialisierung
  • Datenkomprimierung Wenn die Daten über das Netzwerk übertragen werden, müssen wir überlegen, ob die Daten komprimiert werden können.
  • Registrierungscenter: Wenn der Anbieter eine Clusterbereitstellung durchführt (derselbe Dienst wird auf mehreren Computern bereitgestellt), müssen wir eine manuelle Wartung für den Verbraucher durchführen. Wenn das Volumen zunimmt, kann man sich die Arbeitsbelastung vorstellen.
  • Dynamisches Bewusstsein für Online- und Offline-Dienste Wenn der Anbieter ausfällt oder ein neuer Knoten bereitgestellt wird, muss der Verbraucher wissen, welche Dienste offline und welche online sind.
  • Dynamisches Routing: Wenn der Anbieter in einem Cluster bereitgestellt wird (derselbe Dienst wird auf mehreren Computern bereitgestellt), können wir die Verbraucher nicht auf denselben Knoten fallen lassen, sodass die Ressourcen nicht vollständig genutzt werden können Regen und Tau des alten Kaisers werden zu gleichen Teilen geteilt. Dynamisches Routing umfasst eine Vielzahl von Algorithmen wie Randomisierung, Abfrage, Gewichtung usw.
  • Warum wird ein Registrierungszentrum benötigt? Ich habe es schon einmal geteilt:

Meituan-Interview: Wie gestaltet man ein Registrierungszentrum?

造轮子

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

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

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

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!


框架使用

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

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

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

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!


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

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

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

下面,我们来看看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>

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

接着就是properties的配置:

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

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

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";
    }
}

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

最后就是项目启动类:

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

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

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 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

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

再来看看properties配置项:

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

server.port=8090

是不是也很简单?

再来看看我们的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);
    }
}

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

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

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

启动日志:

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

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

Das handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!

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

总结起来,其实就三步:

1、pom中添加依赖

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

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

Das obige ist der detaillierte Inhalt vonDas handgeschriebene RPC-Framework dient wirklich nicht nur dazu, so zu tun, als wäre man 13!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:Java后端技术全栈. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:Was ist der Weg von Laravel?Nächster Artikel:Was ist der Weg von Laravel?

In Verbindung stehende Artikel

Mehr sehen