Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC #183

Open
lovelmh13 opened this issue Oct 13, 2023 · 0 comments
Open

RPC #183

lovelmh13 opened this issue Oct 13, 2023 · 0 comments

Comments

@lovelmh13
Copy link
Owner

在前面的 ACK 文章里提到了 RPC,但是前端可能对 RPC 比较陌生。因为我们都是用 HTTP 请求接口来。
所以我整理了一下 RPC 是什么,以及跟 HTTP 的区别

什么是 RPC

RPC 是远程服务调用。网上一搜搜这么说,但是啥是远程服务调用呢,就是像调用本地的一个函数似的,调用一个远程的函数:

// 服务端
// 假设使用一个RPC框架(比如 gRPC)
const grpc = require('grpc');
const helloProto = grpc.load('hello.proto'); // 加载服务定义文件

const server = new grpc.Server();

// 实现服务
server.addService(helloProto.hello.Greeter.service, {
  sayHello: (call, callback) => {
    const response = { message: 'Hello ' + call.request.name };
    callback(null, response);
  },
});

// 启动服务
server.bind('127.0.0.1:50051', grpc.ServerCredentials.createInsecure());
console.log('Server running at http://127.0.0.1:50051');
server.start();
// 客户端
const grpc = require('grpc');
const helloProto = grpc.load('hello.proto'); // 加载服务定义文件

const client = new helloProto.hello.Greeter('localhost:50051', grpc.credentials.createInsecure());

client.sayHello({ name: 'John Doe' }, (error, response) => {
  if (!error) {
    console.log('Greeting:', response.message);
  } else {
    console.error(error);
  }
});
syntax = "proto3";

package hello;

service Greeter {
  rpc sayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

这里的 hello.proto 的文件,是由 rpc 服务方编写并提供的,用的时候在服务方和调用方都需要各自有一份。
.proto文件包含了服务接口的定义以及消息格式的定义,它是双方进行通信的约定。服务端和客户端分别使用.proto文件来生成对应的代码,以便它们可以相互理解和通信。
在实际项目中,通常会有一个.proto文件的标准版本,它会被服务端和客户端共享。然后,服务端和客户端分别使用这个共享的.proto文件来生成自己需要的代码。
服务端使用.proto文件生成的代码用于实现服务和处理请求,客户端使用.proto文件生成的代码用于调用远程服务。
总的来说,共享一个.proto文件可以确保服务端和客户端之间使用相同的接口定义和消息格式,从而保证了通信的准确性和可靠性。
通俗一点:RPC就是让你可以通过编程语言提供的调用方式(就像调用本地函数一样),去执行远程服务器上的代码,而无需担心底层网络通信的细节。这让分布式系统中的不同部分可以相互通信,实现协作工作。

RPC 调用与 HTTP 的区别

我们前端常用的都是 http 接口请求,那为什么后端的各个服务之前不用 http 接口请求,而用 RPC 调用呢?
这个其实也不是不用 http 请求,都可以用。
不过 RPC 和 HTTP 其实不是一类东西,HTTP 是通信协议,而 RPC 是远程调用,它对应的是本地调用。
RPC 可以通过 HTTP 实现,也可以用过其他的协议或者自定义协议来实现,这个都可以,只要双方都预定好就可以。
HTTP 协议是一个通用标准的协议,我们都按照它来,通信就都没有问题。
RPC 与 HTTP 所在的网络层级也不一样,RPC 可以比 HTTP 的性能更好
在后端把服务都拆成了微服务以后,还想像之前那样调用不同的方法来实现调用,就可以用 RPC 调用,来保证调用方式

为什么要用 RPC 呢?

可能你常听到什么什么之间是 RPC 调用的,那你有没有想过为什么要 RPC, 我们直接 WebClient HTTP 调用不行么?
其实 RPC 调用是因为服务的拆分,或者本身公司内部的多个服务之间的通信。
服务的拆分独立部署,那服务间的调用就必然需要网络通信,用 WebClient 调用当然可行,但是比较麻烦。
我们想即使服务被拆分了但是使用起来还是和之前本地调用一样方便。
所以就出现了 RPC 框架,来屏蔽这些底层调用细节,使得我们编码上还是和之前本地调用相差不多。
并且 HTTP 协议比较的冗余,RPC 都是内部调用所以不需要太考虑通用性,只要公司内部保持格式统一即可。
所以可以做各种定制化的协议来使得通信更高效。
比如规定 yes 代表 yes的练级攻略,你看是不是更高效了,少传输的 5 个字。
就像特殊行动的暗号,高效简洁!
所以公司内部服务的调用一般都用 RPC,而 HTTP 的优势在于通用,大家都认可这个协议。
所以三方平台提供的接口都是通过 HTTP 协议调用的。
所以现在知道为什么我们调用第三方都是 HTTP ,公司内部用 RPC 了吧?
上面这段话看起来仿佛 HTTP 和 RPC 是对等关系,不过相信大家看了之前的解析心里应该都有数了。

  • 性能优化:RPC框架通常比基于HTTP的接口调用更轻量级、高效。这对于需要大量的快速通信的服务来说可能非常重要。
  • 二进制编码:RPC框架通常使用二进制编码来序列化和反序列化消息,这比基于文本的编码(如JSON)更高效,因此在需要高性能通信的情况下更有优势。
  • 强类型:RPC框架通常使用强类型的消息定义,这可以带来更好的类型检查和代码提示,减少了在通信过程中可能出现的错误。
  • 内部服务通信:当你控制所有服务的源码并且可以选择通信协议时,RPC可能更容易集成到你的系统中。
  • 跨语言支持:某些RPC框架(如gRPC)支持多种编程语言,这使得它们可以很容易地在不同的技术栈中进行集成。
  • 分布式系统:在复杂的分布式系统中,使用RPC可以更方便地管理服务之间的通信,并提供一致性和可靠性保证。
  • 性能监控:某些RPC框架提供了丰富的性能监控和追踪功能,这使得在调优和故障排查时更加方便。

总的来说,选择使用RPC调用还是接口调用取决于你的具体需求和技术栈。在一些对性能和效率要求较高的场景下,RPC可能是一个更好的选择。而在简单的应用中,接口调用也可能完全足够。
对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC 框架的好处就显示出来了,首先就是长链接,不必每次通信都要像 HTTP 一样去 3 次握手什么的,减少了网络开销。
其次就是 RPC 框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。

参考

Chatgpt
有了HTTP,为什么还要RPC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant