1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 12:32:21 +00:00

ch4-01: 完善细节

This commit is contained in:
chai2010 2018-07-22 08:08:37 +08:00
parent 87f40d7217
commit a7b8d01b17
2 changed files with 12 additions and 12 deletions

View File

@ -1,10 +1,10 @@
# 4.1. RPC入门
RPC是远程过程调用的简称是分布式系统中不同节点间流行的交互方式。在互联网时代RPC已经是一个不可或缺的基础构件。因此Go语言的标准库提供了一个简单的RPC实现我们将以此为入口学习RPC的各种用法。
RPC是远程过程调用的简称是分布式系统中不同节点间流行的通信方式。在互联网时代RPC已经和IPC一样成为一个不可或缺的基础构件。因此Go语言的标准库提供了一个简单的RPC实现我们将以此为入口学习RPC的各种用法。
## RPC版"Hello, World"
Go语言的RPC包的路径为net/rpc也就是放在了net包目录下面。因此我们可以猜测GoRPC包是建立在net包基础之上的。在第一章“Hello, World”革命一节最后我们基于http实现了一个打印例子。下面我们尝试基于rpc实现一个类似的例子。
Go语言的RPC包的路径为net/rpc也就是放在了net包目录下面。因此我们可以猜测RPC包是建立在net包基础之上的。在第一章“Hello, World”革命一节最后我们基于http实现了一个打印例子。下面我们尝试基于rpc实现一个类似的例子。
我们先构造一个HelloService类型其中的Hello方法用于实现打印功能
@ -17,7 +17,7 @@ func (p *HelloService) Hello(request string, reply *string) error {
}
```
其中Hello方法必须满足Go语言的RPC规则方法只能有两个可序列化的参数其中第二个参数是指针类型并且返回一个error类型。
其中Hello方法必须满足Go语言的RPC规则方法只能有两个可序列化的参数其中第二个参数是指针类型并且返回一个error类型,同时必须是公开的方法
然后就可以将HelloService类型的对象注册为一个RPC服务
@ -39,7 +39,7 @@ func main() {
}
```
其中rpc.Register会将对象类型中所有满足RPC规则的对象方法注册为RPC函数。然后我们建立一个唯一的TCP链接并且通过rpc.ServeConn方法在该TCP链接上建立RPC服务。
其中rpc.Register函数调用会将对象类型中所有满足RPC规则的对象方法注册为RPC函数所有注册的方法会放在“HelloService”服务空间之下。然后我们建立一个唯一的TCP链接并且通过rpc.ServeConn函数在该TCP链接上为对方提供RPC服务。
下面是客户端请求HelloService服务的代码
@ -146,7 +146,7 @@ func main() {
现在客户端用户不用再担心RPC方法名字或参数类型不匹配等低级错误的发生。
最后是基于RPC接口规范编写真实的代码
最后是基于RPC接口规范编写真实的服务端代码:
```go
type HelloService struct {}
@ -175,16 +175,16 @@ func main() {
}
```
在新的RPC服务端实现中我们用RegisterHelloService函数来注册函数这样不仅可以避免命名服务名称的工作同时也保证了传入的服务对象满足了RPC接口的定义。最后我们支持多个TCP链接然后为每个TCP链接建立RPC服务。
在新的RPC服务端实现中我们用RegisterHelloService函数来注册函数这样不仅可以避免命名服务名称的工作同时也保证了传入的服务对象满足了RPC接口的定义。最后我们新的服务改为支持多个TCP链接然后为每个TCP链接提供RPC服务。
## 跨语言的RPC
标准库的RPC默认采用Go语言特有的gob规范编码因此从其它语言调用Go语言实现的RPC服务将比较困难。在互联网的微服务时代每个RPC以及服务的使用者都可能采用不同的编程语言因此跨语言是互联网时代RPC的一个首要条件。得益于RPC的框架设计Go语言的RPC其实也是很容易实现跨语言支持的。
标准库的RPC默认采用Go语言特有的gob编码因此从其它语言调用Go语言实现的RPC服务将比较困难。在互联网的微服务时代每个RPC以及服务的使用者都可能采用不同的编程语言因此跨语言是互联网时代RPC的一个首要条件。得益于RPC的框架设计Go语言的RPC其实也是很容易实现跨语言支持的。
Go语言的RPC框架有两个比较有特色的设计一个是RPC数据打包时可以通过插件实现自定义的编码和解码另一个是RPC建立在抽象的io.ReadWriteCloser接口之上的我们可以将RPC架设在不同的通讯协议之上。这里我们将尝试通过官方自带的net/rpc/jsonrpc扩展实现一个跨语言的PPC。
首先是基于json实现RPC服务
首先是基于json编码重新实现RPC服务
```go
func main() {
@ -206,7 +206,7 @@ func main() {
}
```
中最大的变化是用rpc.ServeCodec函数替代了rpc.ServeConn函数传入的参数是针对服务端的json编解码器。
代码中最大的变化是用rpc.ServeCodec函数替代了rpc.ServeConn函数传入的参数是针对服务端的json编解码器。
然后是实现json版本的客户端
@ -231,7 +231,7 @@ func main() {
先手工调用net.Dial函数建立TCP链接然后基于TCP信道建立针对客户端的json编解码器。
在确保客户端可以正常调用RPC服务的方法之后我们用一个普通的TCP服务代替Go语言版本的RPC服务。比如通过nc命令`nc -l 1234`在同样的端口启动一个TCP服务。然后再次执行一次RPC调用将会发现nc输出了以下的信息
在确保客户端可以正常调用RPC服务的方法之后我们用一个普通的TCP服务代替Go语言版本的RPC服务,这样可以查看客户端调用时发送的数据格式。比如通过nc命令`nc -l 1234`在同样的端口启动一个TCP服务。然后再次执行一次RPC调用将会发现nc输出了以下的信息
```json
{"method":"HelloService.Hello","params":["hello"],"id":0}
@ -313,7 +313,7 @@ func main() {
}
```
RPC的服务架设在“/jsonrpc”路径在处理函数中基于http.ResponseWriter和http.Request类型的参数构造一个io.ReadWriteCloser类型的conn通道。然后基于conn构建针对服务端的json编码解码器。最后通过rpc.ServeRequest处理一次RPC方法调用。
RPC的服务架设在“/jsonrpc”路径在处理函数中基于http.ResponseWriter和http.Request类型的参数构造一个io.ReadWriteCloser类型的conn通道。然后基于conn构建针对服务端的json编码解码器。最后通过rpc.ServeRequest函数为每次请求处理一次RPC方法调用。
模拟一次RPC调用的过程就是向该链接发送一个json字符串

View File

@ -1,3 +1,3 @@
# 第四章 RPC和Protobuf
RPC是远程过程调用的缩写Remote Procedure Call通俗地说就是调用远处的一个函数。远处到底有多远呢可能是同一个文件内的不同函数也可能是同一个机器的另一个进程的函数还可能是远在火星好奇号上面的某个秘密方法。因为RPC涉及的函数可能非常之远远到它们之间说着完全不同的语言语言将成为两边的沟通障碍。而Protobuf因为支持多种不同的语言甚至不支持的语言也可以扩展支持其本身特性也非常方便描述服务的接口也就是方法列表因此非常适合作为RPC世界的接口交流语言。本章将讨论RPC的基本用法以及如何针对不同场景设计自己的RPC服务以及围绕Protobuf构造的更为庞大的RPC生态。
RPC是远程过程调用的缩写Remote Procedure Call通俗地说就是调用远处的一个函数。远处到底有多远呢可能是同一个文件内的不同函数也可能是同一个机器的另一个进程的函数还可能是远在火星好奇号上面的某个秘密方法。因为RPC涉及的函数可能非常之远远到它们之间说着完全不同的语言语言就成了两边的沟通障碍。而Protobuf因为支持多种不同的语言甚至不支持的语言也可以扩展支持其本身特性也非常方便描述服务的接口也就是方法列表因此非常适合作为RPC世界的接口交流语言。本章将讨论RPC的基本用法如何针对不同场景设计自己的RPC服务以及围绕Protobuf构造的更为庞大的RPC生态。