ホームページ  >  記事  >  手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

Java后端技术全栈
Java后端技术全栈転載
2023-08-16 17:01:18710ブラウズ

面接中に、面接官から次のような質問を受けやすいです。

RPC フレームワークを設計するにはどうすればよいですか ?

あなたは質問されていないかもしれません、おそらくあなたは幸運であるかもしれません、あるいはあなたはまだこのレベルに達していないかもしれません。通常、月給は20,000以上で、基本的にデザインに関する質問をいくつか受けます。

面接官の観点から: この種の質問をすることは、多くの技術的なポイントを含む 8 部構成のエッセイよりも優れています。例: デザイン パターン、通信プロトコル、動的エージェント、仮想化、スレッド プールなどに関する知識。

さて、あまり話はやめて、今日のテーマについて話しましょう。

RPC はリモート プロシージャ コールです。この言葉をよく理解していない人も多いかもしれません。簡単に言うと、

ローカルを呼び出すようなものです。方法は同じです。リモートサービスを呼び出しています。

たとえば、次の場合: ユーザーがサービスを操作します:

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

ここで、コントローラーは UserServiceImpl の findUserNameById メソッドを呼び出してユーザー名を取得したいと考えています。

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

3 つのクラス UserController、UserServiceImpl、および UserService がすべて同じプロジェクト内にあると仮定すると、コントローラーが findUserNameById メソッドを呼び出すのは非常に簡単です。

ただし、コントローラーが別のプロジェクトであり、上記のように呼び出されたい場合 (微妙な違いがありますが、感覚は同じです)、RPC フレームワークを使用できます。

1. インターフェイス UserService は、通常 API プロジェクトと呼ばれる別のプロジェクトに配置する必要があります。

2. UserServiceImpl は、通常プロバイダー プロジェクトと呼ばれる別のプロジェクトに配置する必要があります。

3. コントローラー、Web またはその他の (消費者) プロジェクト経由

4. API を jar パッケージに入力し、それをコンシューマー プロジェクトとプロバイダー プロジェクトの両方で参照します。

Dubbo (Alibaba)、Thrift (FaceBook)、gRpc (Google)、brpc (Baidu) などの市販の RPC フレームワークはすべて、問題を解決するためのさまざまな側面に焦点を当てています。極限の完璧さを求める人もいれば、極限のパフォーマンスを追求する人もいるし、極限のシンプルさを好む人もいます。

RPC 原則

先ほどの話に戻りますローカル サービスを呼び出すのと同じようにリモート サービスを呼び出す、どのような技術サポートが必要ですか?

  • 動的プロキシ、コンシューマ プロジェクトにはインターフェイス UserService のみが定義されており、実装クラスがないためです。のメソッドを呼び出しますか?インターフェースは?この場合、プロキシ オブジェクトを作成することしかできません。
  • エンコーディング、つまり、コンシューマはリクエスト パラメータをプロバイダに渡す必要があります。ネットワーク送信プロセスでは、最初にパラメータをエンコードしてからプロバイダに渡します。次に、プロバイダーは渡されたパラメーターをデコードします。
  • ネットワーク通信、クロスプロセスにはネットワーク通信が必ず含まれます。
  • ネットワーク伝送プロトコル、消費者とプロバイダーは、行き来するパラメータ情報の標準を持っている必要があります。それを私に渡すにはどうすればよいですか? それ以外の場合、私はどのようにしますか?あなたは何を表現したいのかを知っています。
  • シリアル化と逆シリアル化
  • データ圧縮、データ ネットワーク送信中に、データが大きすぎる場合は、データを圧縮できるかどうかを検討します。
  • 登録センター、プロバイダーがクラスター展開を実行する場合 (同じサービスが複数のマシンに展開される場合)、コンシューマで手動メンテナンスを実行する必要があります。ボリュームが大きい 立ち上がると、作業量が想像できます。
  • サービスのオンラインとオフラインの動的な認識、プロバイダーがダウンしている場合、または新しいノードがデプロイされている場合、コンシューマーはどのサービスがオフラインでどのサービスがオフラインであるかを知る必要があります。ライン上のサービス。
  • 動的ルーティング、プロバイダーがクラスターにデプロイされている場合 (同じサービスが複数のマシンにデプロイされている場合)、すべてのコンシューマーを同じノードに配置することはできません。 、そのため、リソースを最大限に活用することができず、古代皇帝の 雨露はすべて に染まります。動的ルーティングには、ランダム化、ポーリング、重み付けなどのさまざまなアルゴリズムが含まれます。

なぜ登録センターが必要なのでしょうか? 以前に共有しました:

Meituan インタビュー: 登録センターを設計するにはどうすればよいですか?

造轮子

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

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

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

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。


框架使用

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

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

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

手書きの RPC フレームワークは、実際には 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):

手書きの RPC フレームワークは、実際には 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);
    }
}

启动日志:

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

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

手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。

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

总结起来,其实就三步:

1、pom中添加依赖

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

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

以上が手書きの RPC フレームワークは、実際には 13 歳のふりをするためだけのものではありません。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はJava后端技术全栈で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。