前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Go RPC入门指南:RPC的使用边界在哪里?如何实现跨语言调用?

Go RPC入门指南:RPC的使用边界在哪里?如何实现跨语言调用?

作者头像
王中阳Go
发布于 2022-10-26 07:08:42
发布于 2022-10-26 07:08:42
44900
代码可运行
举报
文章被收录于专栏:Go语言学习专栏Go语言学习专栏
运行总次数:0
代码可运行

RPC

什么是RPC

  1. RPC的中文是“远程过程调用”,对应的英文全称是:Remote Procedure Call,可以简单理解为一个节点请求另一个节点提供的服务
  2. 理解“本地过程调用”可以更好的理解“远程过程调用”
  3. 知识点:RPC主要依赖于客户端与服务端建立socket链接;而HTTP REST实现通讯的代价比较高,这是RPC的一个优势体现。
  4. RPC详解看这里

为什么用RPC

就是因为无法在同一个进程内,或者无法在同一个服务器上通过本地调用的方式实现我们的需求。HTTP能满足需求但是不够高效,所以我们需要使用RPC。

RPC的优势

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

RPC和HTTP对比

  1. RPC主要用于公司内部的服务调用,性能消耗低,传输效率高,服务治理方便。
  2. HTTP主要用于对外的异构环境,浏览器接口调用,APP接口调用,第三方接口调用等。
  3. RPC和HTTP的详细对别

RPC的使用边界

  1. 通过和HTTP的对比,我们倒推出RPC的边界:对外的异构环境,浏览器接口调用,APP接口调用,第三方接口调用。
  2. 上述这些都不适合RPC,不知道RPC不适合做什么,比知道RPC能做什么更重要。

RPC入门1:net/rpc

基本构成

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

代码示例

rpc_service.go

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)
}
复制代码

运行结果

  1. 先启动服务端,再启动客户端连接服务端
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//服务端console
start connection

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

复制代码

RPC入门2:net/rpc/jsonrpc

实现跨语言调用

jsonrpc_server.go

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)
}
复制代码

运行结果

  1. 先启动服务端,再启动客户端连接服务端
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//服务端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服务端的代码一样

jsonrpc_client.php

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//本地启动PHP服务:http://127.0.0.1/jsonrpc_client.php,运行结果如下:
9 * 2 = 18 9 / 2, Quo is 4, Rem is 1
复制代码

参考博客

  • RPC相关博客,可以点击原文链接查看
  • Mac本地启动PHP,可以点击原文链接查看

名词解释

  • Thrift:是一种接口描述语言和二进制通讯协议,被当做RPC的框架来使用。

思考

如何优雅的使用RPC进行web开发

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员升级打怪之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Nginx编译安装以及选项
编译安装Nginx 1、安装常见的工具和库(GCC、PCRE、zlib、OpenSSL)
星哥玩云
2022/07/14
9570
LNMP之Nginx
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。 其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/PO
用户1173509
2018/03/28
1K0
LNMP之Nginx
Nginx(一)安装及启停
    我发现很多博客排版杂乱,表达不清,读者看了往往云里雾里。我此前的博客也是如此,我自己很不满意。今起,每一篇博客都会用心写,此前的博客我也会尽力修改。至少要做到排版整洁,让自己满意,让别人能看懂。
用户1432189
2018/09/05
8670
Nginx(一)安装及启停
重识Nginx - 02 手把手教你编译适合自己的nginx 1.22.0
文章目录 编译Nginx 下载nginx 1.22.0 step 2 解压 编译 (这里我们只指定 prefix,其他默认 ) make 编译 make install 安装 Configure的命令参数 编译Nginx 下载nginx 1.22.0 https://nginx.org/en/download.html 复制链接地址 ,下载 1.22.0 [root@VM-0-7-centos ng]# wget https://nginx.org/download/nginx-1.22.0.
小小工匠
2022/09/27
8050
重识Nginx - 02 手把手教你编译适合自己的nginx 1.22.0
Linux下Nginx源码编译安装
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器,在高连接并发的情况下Nginx 是 Apache 服务器不错的替代品.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好.目前中国大陆使用nginx网站用户有:新浪、网易、 腾讯,另外知名的微网志Plurk也使用nginx。 
星哥玩云
2022/07/19
1.9K0
linux下编译安装nginx完整版
0x01 Nginx有哪些优点 更快 这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应; 另一方在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请 高扩展性 Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极 低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须 在意其他。 高可靠性 Nginx的高可靠性来自于其核心框架代码 的优秀设计、模块设计的简单性;官方提供的常用模块都非常稳定,每个worker进
小柒吃地瓜
2020/04/23
15.5K1
linux主要发行版安装nginx教程
[nginx] name=nginx repo baseurl=http://nginx.org/packages/OS/OSRELEASE/$basearch/ gpgcheck=0 enabled=1
ianzhi
2019/07/31
2.5K0
linux主要发行版安装nginx教程
Nginx编译安装参数详解
./configure --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio
非著名运维
2022/06/22
1.6K0
Nginx编译安装参数详解
2.Nginx进阶学习之最佳配置实践指南
描述:在企业线上生产环境中推荐进行Nginx编译安装,可以按照业务侧重点进行相应 Nginx 编译参数配置,所以编译参数不是功能加的越多越好,应该尽可能少编译模块不用的最好不要加入,本小结将以最新的Nginx版本以及依赖版本进行编译演示。
全栈工程师修炼指南
2022/09/29
2K0
2.Nginx进阶学习之最佳配置实践指南
OpenNJet如何做到让用户永远在线
最近看到了国内开源的一个名为OpenNJet的项目,有一个响亮的口号:“下一代云原生应用引擎”。
手撕代码八百里
2024/05/24
990
OpenNJet如何做到让用户永远在线
Nginx 模块(1)
Nginx (engine x) 可以作为 HTTP 和反向代理服务器,也可以作为邮件代理和普通的 TCP/UDP 代理服务器
franket
2021/10/18
5020
爬虫、代理和Nginx
做过爬虫的人应该都知道,抓的网站和数据多了,如果爬虫抓取速度过快,免不了触发网站的防爬机制,几乎用的同一招就是封IP。解决方案有2个:
后端技术探索
2018/10/18
2.1K0
爬虫、代理和Nginx
nginx 学习之反向代理(1)
你可以在http模块内部、server或location里面配置日志(日志格式指定为main或者定义其他日志格式)
用户2825413
2019/07/16
3570
Centos下安装FastDFS
FastDFS运行需要一些依赖,在课前资料提供的虚拟中已经安装好了这些依赖,如果大家想要从头学习,可以按下面方式安装:
用户4396583
2024/07/25
1500
nginx编译参数详解
Nginx 使用 liunx/Unix 下常用的 ‘./configure && make && make install’ 过程来编译安装。 configure 脚本确定系统所具有一些特性,特别是 nginx 用来处理连接的方法。然后,它创建 Makefile 文件。 configure 支持下面的选项: –prefix=<path> – Nginx安装路径。如果没有指定,默认为 /usr/local/nginx。 –sbin-path=<path> – Nginx可执行文件安装路径。只能安装时指定,
苦咖啡
2018/05/07
1.2K0
Nginx入门详解文档
Nginx入门详解文档 1 文章内容 掌握nginx+tomcat反向代理的使用方法。 掌握nginx作为负载均衡器的使用方法。 掌握nginx实现web缓存方法。 2 nginx介绍 2.1 什么是nginx Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。 3 nginx安装 3.1 下载 进入http://nginx.org/en/download.html
Java帮帮
2018/03/15
1.4K0
Nginx入门详解文档
nginx 基础
nginx -s quit:优雅停止,工作线程完成工作,以启动nginx的用户关闭;同系统命令:kill -s QUIT pid
WindWant
2020/09/11
8140
Nginx 动态编译加载第三方流媒体服务模块:Nginx-RTMP-Module
Nginx 1.9.11开始增加加载动态模块支持,可以在不停机的情况下加载和卸载模块。从此不再需要替换nginx文件即可增加第三方扩展。目前官方只有几个模块支持动态加载,第三方模块需要升级支持才可编译成模块。
Tinywan
2024/03/02
5070
Nginx 动态编译加载第三方流媒体服务模块:Nginx-RTMP-Module
Nginx源码安装及调优配置
由于Nginx本身的一些优点,轻量,开源,易用,越来越多的公司使用nginx作为自己公司的web应用服务器,本文详细介绍nginx源码安装的同时并对nginx进行优化配置。 image.png Nginx编译前的优化 [root@linuxprobe ~]# wget http://nginx.org/download/nginx-1.10.1.tar.gz [root@linuxprobe ~]# tar xvf nginx-1.10.1.tar.gz -C /usr/local/src/ [root@l
shaonbean
2018/01/15
2.1K0
Nginx源码安装及调优配置
Nginx流媒体支持配置
有关Nginx相关的基础知识 Linux 6下安装编译安装Nginx Nginx 概述及日常管理 Nginx基于IP,端口,域名配置虚拟主机 Linux 下配置nginx到php的连接
Leshami
2018/08/08
1.4K0
相关推荐
Nginx编译安装以及选项
更多 >
LV.0
不告诉你运维工程师
目录
  • 什么是RPC
  • 为什么用RPC
  • RPC的优势
  • RPC和HTTP对比
  • RPC的使用边界
  • RPC入门1:net/rpc
    • 基本构成
    • 代码示例
    • 运行结果
  • RPC入门2:net/rpc/jsonrpc
    • 实现跨语言调用
    • 运行结果
  • RPC入门3:go php跨语言调用
    • Go作为服务端,PHP作为客户端
    • 运行结果
  • 参考博客
  • 名词解释
  • 思考
    • 如何优雅的使用RPC进行web开发
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档