文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文搞懂RPC,So Easy!

2024-11-30 16:15

关注

请先自行思考一下什么是“本地过程调用”,可以更好的理解“远程过程调用”。

知识点:RPC主要依赖于客户端与服务端建立socket链接;而HTTP REST实现通讯的代价比较高,这是RPC的一个优势体现。(gRPC使用http2.0)

为什么用RPC

就是因为无法在同一个进程内,或者无法在同一个服务器上通过本地调用的方式实现我们的需求。

HTTP能满足需求但是不够高效,所以我们需要使用RPC。

知乎大神的回答[1]

RPC的优势

  1. RPC能够跨多种开发工具和平台
  2. RPC能够跨语言调用
  3. RPC能够提高系统的可扩展性,解耦,提高复用
  4. RPC相较于HTTP 1.1,传输效率更高,性能消耗更小,自带负载均衡策略,自动实现服务治理

RPC和HTTP对比

RPC的使用边界

通过和HTTP的对比,我们可以倒推出RPC的边界:对外的异构环境,浏览器接口调用,APP接口调用,第三方接口调用。

上述这些都不适合RPC,不知道RPC不适合做什么,比知道RPC能做什么更重要。

RPC入门1:net/rpc

基本构成

  1. RPC的基本构成:服务端,客户端
  2. 服务端基本构成:结构体,请求结构体,响应结构体
  3. 客户端基本构成:请求结构体,响应结构体

代码示例

rpc_service.go

package main

import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"os"
)

type Arith struct {

}

//请求结构体
type ArithRequest struct {
A int
B int
}

//响应结构体
type ArithResponse struct {
Pro int //乘积
Quo int //
Rem int //余数
}

//乘积方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}

//除法运算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
//注册rpc服务
rpc.Register(new(Arith))
//采用http协议作为rpc载体
rpc.HandleHTTP()

lis,err := net.Listen("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("fatal error:",err)
}

fmt.Fprintf(os.Stdout,"%s","start connection\n")

//常规启动http服务
http.Serve(lis,nil)
}

rpc_client.go

package main

import (
"fmt"
"log"
"net/rpc"
)

//算数运算请求结构体
type ArithRequest struct {
A int
B int
}

//响应结构体
type ArithResponse struct {
Pro int //
Quo int //
Rem int //余数
}

func main() {
conn,err := rpc.DialHTTP("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("dialing error:",err)
}

req := ArithRequest{10,20}
var res ArithResponse

err = conn.Call("Arith.Multiply",req,&res) //乘法运算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)

//除法运算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余数是:%d",req.A,req.B,res.Quo,res.Rem)
}

运行结果

先启动服务端,再启动客户端连接服务端

//服务端console
start connection

//客户端console
10 * 20 = 200
10 / 20 = 0 余数是:10

RPC入门2:net/rpc/jsonrpc

实现跨语言调用

jsonrpc_server.go

package main

import (
"errors"
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"os"
)

type Arith struct {

}

//请求结构体
type ArithRequest struct {
A int
B int
}

//响应结构体
type ArithResponse struct {
Pro int //乘积
Quo int //
Rem int //余数
}

//乘积方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}

//除法运算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
//注册rpc服务
rpc.Register(new(Arith))
//采用http协议作为rpc载体
rpc.HandleHTTP()

lis,err := net.Listen("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("fatal error:",err)
}

fmt.Fprintf(os.Stdout,"%s","start connection\n")

//接收客户端请求 并发处理 jsonrpc
for {
conn,err :=lis.Accept() //接收客户端连接请求
if err!=nil {
continue
}

//并发处理客户端请求
go func(conn net.Conn) {
fmt.Fprintf(os.Stdout,"%s","new client in coming\n")
jsonrpc.ServeConn(conn)
}(conn)
}

//常规启动http服务
//http.Serve(lis,nil)
}

jsonrpc_client.go

package main

import (
"fmt"
"log"
"net/rpc/jsonrpc"
)

//算数运算请求结构体
type ArithRequest struct {
A int
B int
}

//响应结构体
type ArithResponse struct {
Pro int //
Quo int //
Rem int //余数
}

func main() {
// 只有这里不一样
conn,err := jsonrpc.Dial("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("dialing error:",err)
}

req := ArithRequest{9,2}
var res ArithResponse

err = conn.Call("Arith.Multiply",req,&res) //乘法运算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)

//除法运算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余数是:%d",req.A,req.B,res.Quo,res.Rem)
}

运行结果

先启动服务端,再启动客户端连接服务端

//服务端console
start connection

//客户端console
9 * 2 = 18
9 / 2 = 4 余数是:1

//服务端console
new client in coming

RPC入门3:go php跨语言调用

Go作为服务端,PHP作为客户端

jsonrpc_server.go:和入门2服务端的代码一样

下面是PHP代码

jsonrpc_client.php

<?php
class JsonRPC
{

private $conn;

function __construct($host, $port)
{
$this->conn = fsockopen($host, $port, $errno, $errstr, 3);
if (!$this->conn) {
return false;
}
}

public function Call($method, $params)
{
if (!$this->conn) {
return false;
}
$err = fwrite($this->conn, json_encode(array(
'method' => $method,
'params' => array($params),
'id' => 0,
)) . "\n");
if ($err === false) {
return false;
}
stream_set_timeout($this->conn, 0, 3000);
$line = fgets($this->conn);
if ($line === false) {
return NULL;
}
return json_decode($line, true);
}
}

$client = new JsonRPC("127.0.0.1", 8096);
$args = array('A' => 9, 'B' => 2);
$r = $client->Call("Arith.Multiply", $args);
printf("%d * %d = %d\n", $args['A'], $args['B'], $r['result']['Pro']);
$r = $client->Call("Arith.Divide", array('A' => 9, 'B' => 2));
printf("%d / %d, Quo is %d, Rem is %d\n", $args['A'], $args['B'], $r['result']['Quo'], $r['result']['Rem']);

如何在本地启动PHP[3] 不作为本文重点,可以看这篇文章。

运行结果

本地启动PHP服务:

​http://127.0.0.1/jsonrpc_client.php​

运行结果如下:

9 * 2 = 18 9 / 2, Quo is 4, Rem is 1

总结

一文入门RPC,就是如此丝滑,So Easy!

欢迎还在用单体架构,没有使用RPC的同学们操练起来,尤其是PHP的小伙伴们,卷起来吧。该学学Go语言啦~

相关资料

[1]知乎大神的回答: https://www.zhihu.com/question/25536695

[2]RPC和HTTP的详细对别: http://www.ccutu.com/244407.html

[3]如何在本地启动PHP: ​​https://blog.csdn.net/resilient/article/details/80770531​

本文转载自微信公众号「 程序员升级打怪之旅」,作者「王中阳Go」,可以通过以下二维码关注。

转载本文请联系「 程序员升级打怪之旅」公众号。

来源:程序员升职加薪之旅内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯