上海中艺建设集团网站,商派商城网站建设方案,连平网站建设,网站建设与管理维护 大学论文grpc简介
grpc介绍可以参考官网。无论是rpc还是grpc#xff0c;可以这样理解#xff0c;都知道过去使用的单单体架构#xff0c;而在2011年5月威尼斯的一个软件架构会议上提出了微服务架构#xff0c;围绕业务功能进行组织(organized around business capability)#xf…grpc简介
grpc介绍可以参考官网。无论是rpc还是grpc可以这样理解都知道过去使用的单单体架构而在2011年5月威尼斯的一个软件架构会议上提出了微服务架构围绕业务功能进行组织(organized around business capability)不再是以前的纵向切分而改为按业务功能横向划分一个微服务最好由一个小团队针对一个业务单元来构建。 所以服务和服务之间存在调用关系服务中之间使用http调用发现性能太差使用了一种新的通信方式这个通信方式称为rpc客户端和服务端沟通的过程如下
客户端发送数据以字节流的方式编码服务端接受并解析根据约定执行什么然后把结果返回给客户解码 那RPC的发展RPC远程调用总体而言:rpc就是上述的过程封装下时期操作更加优化使用一些大家都认可的协议使其规范化做成一些框架直接或间接的产生利益这个就是grpc
grpc是基于“服务定义”的思想简单的来说就是通过某种方式描述一个服务这种描述与语言无关在这个“服务定义”的过程中描述了提供的服务名是什么有哪些方法可以被调用这些方法有哪些参数返回参数是什么
grpc调用方称之为client服务方为server。也就是说定义好了这些方法和服务之后grpc会屏蔽底层的细节client只需要调用定义好的防范就能返回预期的结果对server段来说还需要实现定义的方法。
proto创建
这里结合grpc-study实例介绍按照如下目录创建工程和文件仅有hello.proto中存在代码
proto是一种语法类似go中约定变量定义var name string一样python中variable1一样的语法规定。proto中也有自己的语法比如使用message使用service关键字 hello.proto代码如下
syntax proto3;// 这部分内容是关于最后生成的go文件的是放在哪个目录哪个包中的 .代表在当前目录生成service代表了生成go文件的包名是service
option go_package.;service;// 这里定义一个服务这个份服务需要有一个方法这个方法可以接受客户端的参数请求再返回服务端的响应这个方法是以rpc就像func标记一个函数一行这个rpc标记的是一个rpc的方法
// 其实可以看出定义了一个service,称之为SayHello这个服务有一个rpc的方法名为SayHello
// 这个方法会发送一个HelloRequest然后返回一个 HelloResponse
service SayHello {rpc SayHello(HelloRequest) returns (HelloResponse) {}
}// 既然是约定的一些规则这里需要使用message关键字顶一个结构体这个message类似go中的struct
// 这里比较特殊的是变量后的赋值这里不是赋值而是在定义这个变量在这个message中的位置可以理解为显示的定义了该参数在message数组或者结构体的索引位置
// 最终生成代码的时候就会根据标识号来生成对应的位置如requestName在第一个位置就会生成在第一个
message HelloRequest {string requestName 1;
}message HelloResponse {string response 1;
}// 以上是一个约束规则就是一个语法规定terminal切换到 grpc-service下
grpc-study % cd hello-server\proto切换该目录后在和*.proto同级目录执行如下命令
protoc --go_out. hello.proto // 使用go_out生成需要的go语言的文件
protoc --go-grpc_out. hello.proto // 使用go_out生成需要的rpc语言的文件执行完成后在proto下新增两个文件如下所示 对于远程过程调用就使用的grpc中的代码。 所以关于proto的总结如下
创建工程项目设置文件分层编写proto文件(切换目录)使用go-out生成pb.go使用go-grpc_out命令生成gprc.pb.go文件
proto文件介绍
messagemessageprotobul定义了一个消息类型是通过关键字message字段指定消息就是要传输的数据格式的定义message类似go中的struct在消息中承载的数据分别对应的是一个字段每个字段都有一个名字和一种类型。每个字段有一些规则
required消息体中的必填字段不设置时会导致编码异常在protobf2中使用在protobuf3中删除optional消息体中的可选字段protobuf3中取消了required和optional等说明关键字默认都是optionalrepeated消息中的可重复字段重复的值的顺序会被保留在go中重复的会被定义为切片使用repeadted可以理解为类似数组 每个字段都必须有一个唯一的标识好一般不建议一个消息号中超过15当然消息也可以嵌套定义
message PersonInfomation {message Person {string name 1;int32 height 2;repeated int32 age 3;}repeated Person info 1;
}如果要在父消息类型的外部重用这个消息类型需要PersonInformation.Person的形式使用它如
message PersonMessage {PersonInformation.Person info 1;
}
既然是用于微服务如果想要将消息类型用在RPC的系统中可以在**.proto文件中定义一个RPC服务接口protocol buffer编译器将会更具所选择的不同语言生成服务接口代码和存根
service SearchService {// rpc 服务函数名 参数名返回 (返回参数)rpc Search(SearchRquest) returns (SearchResponse)
}这样就定义了了RCP的服务该方法接受SearchRequest请求和SearchResponse响应.所以这个*.proto文件中的格式只是一个约定规定就像go的函数使用func声明是一个函数*.proto中也有自己的一些约束。有了这些约束之后客户端和服务端都是去调用这些接口的有了这些约束之后grpc可以帮助我们去寻路用什么方法写的就调用什么方法就可以。
服务端实现
有了上面的*.proto的约束之后就可以遵循该声明实现服务端的接口调用服务端实现如下
创建gRPC Server对象我们可以理解他是Server端的抽象对象将Server(包含需要被调用的服务端接口)注册到gRPC Server的内部注册中心这样可以在服务端接受请求时通过内部的服务发现发现该服务器接口并转接进行逻辑处理创建Listen监听TCP端口gRPC Server开始lis.Accept直到Stop 上面定义了server中的方法这里来具体实现在serverice下的main.go中
package mainimport (contextfmtgoogle.golang.org/grpcpb grpc-study/hello-server/protonet
)// hello server
type server struct {pb.UnimplementedSayHelloServer
}func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {fmt.Printf(hello req.RequestName)return pb.HelloResponse{Response: hello req.RequestName}, nil
}func main() {// 开启端口监听listen, _ : net.Listen(tcp, 9090)// 把这个服务暴露其他服务使用grpcServer : grpc.NewServer()//在grpc服务端中去注册自己编写的服务pb.RegisterSayHelloServer(grpcServer, server{})//创建服务完成后启动该服务err : grpcServer.Serve(listen)if err ! nil {fmt.Printf(failed to server: %, err)return}
}// 如何实现具体逻辑呢在grpc.pb.go中找到源码实现对应的方法逻辑就行了
客户端实现
有了上面的*.proto的约束之后就可以遵循该声明实现服务端的接口调用服务端实现如下
创建于给定目标服务端的连接交互创建server的客户端对象发送RPC对象等待同步响应得到回调后返回响应结果输出响应结果
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecurepb grpc-study/hello-server/protolog
)func main() {// 连接打server端次数禁用安全传输没有加密和验证conn, err : grpc.Dial(127.0.0.1:9090, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(did not connect: %v, err)}defer conn.Close()//建立连接client : pb.NewSayHelloClient(conn)// 执行rpc调用(这个方法时在服务器端来实现并返回结果)resp, _ : client.SayHello(context.Background(), pb.HelloRequest{RequestName: zhiyu})fmt.Println(resp.GetResponse())
}先执行server中的main.go再执行执行client中的main.go检查执行结果未来只要能找到127.0.0.:9090这个地址就可以调用到服务并可以拿到返回结果。goland IDE界面分屏执行两个main.go函数
这里注意到client/main.go中
func main() {// 连接打server端此处禁用安全传输没有加密和验证conn, err : grpc.Dial(127.0.0.1:9090, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(did not connect: %v, err)}只要能访问到该地址信息就可以拿到返回结果因此这种是不安全的所以需要进行加密安全传输。 经过前文的学习我们直到gRPC是一个C/S模型需要开户客户端和服务端客户端和服务端需要达成协议使用某一个确认的传输协议来传输数据gPRC通过默认使用protobuf作为传输协议当然也可以使用其他的自定义协议创建如你可以使用xml。接着再看grpc官网中的这个示意图就可以如下表示
客户端和服务端通信之前客户端如何知道自己的数据发送给哪个明确的服务端呢反过来服务端是如何知道将数据返回给谁呢这个就需要gRPC认证。 此处说到的认证,不是用户的身份认证,而是指多个server和多个client之间,如何识别对方是谁,并且可以安全的进行数据传输可以通过如下的几种方式
SSL/TLS认证方式(采用http2协议)基于Token的认证方式(基于安全连接)不采用任何措施的连接,这是不安全的连接(默认采用http1)自定义的身份认证 客户端和服务端之间调用,我们可以通过加入证书的方式,实现调用的安全性 TLS(Transport Layer Security,安全传输层),TLS是建立在传输层TCP协议之上的协议,服务于应用层,它的前身是SSL(Secure Socket Layeer, 安全套接字层),它实现了将应用层的报文进行加密后再交由TCP进行传输的功能。 TLS协议主要解决如下三个网络安全问题。
保密(message privacy),保密通过加密encryption实现,所有信息都加密传输,第三方无法嗅探;完整性(message integrity),通过MAC校验机制,一旦被篡改,通值双方会立刻发现;认证(mutual authentication),双方认证,双方都可以配备证书,防止身份被冒充 生存环境可以购买证书或者使用一些平台发放的证书
key:服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接受到数据的解密csr:证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名。crt:由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息pem:是基于Base64编码的证书格式,扩展名包括PEM、CRT和CER
SSL/TLS认证方式
首先通过openssl生成证书和私钥关于认证方式参考https://www.kuangstudy.com/bbs/1604044550878703617
官网下载:https://www.openssl.org/source/ 便捷版安装包http://slproweb.com/products/Win320penSSL.html我们使用便捷版安装包,一直下一步即可配置环境变量 D:\Environment\OpenSSL-Win64\bin命令行测试 openssl
生成证书步骤如下,mac安装ssl参考https://www.freesion.com/article/7165613046/
#1、生成私钥
openssl genrsa -out server.key 2048
#2、生成证书全部回车即可,可以不填
openss1 req -new -x509 -key server.key -out server.crt -days 36500
#国家名称
Country Name (2 letter code) [AU] :CN
#省名称
State or Province Name (full name) [Some-State]:GuangDong
#城市名称
Locality Name (eg, city) []:Meizhou
#公司组织名称
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Xuexiangbar
#部门名称
Organizational Unit Name (eg, section) []:go
#服务器or网站名称
Common Name
# 邮件
(e.g. server FQDN or YOUR name) []:kuangstudy
Email Address []:24736743qq.com# 3、生存csr
openssl req -new -key server.key -out server.cs#更改openssl.cnf (Linux 是openssl.cfg)
#1)复制一份你安装的openssl的bin目录里面的openssl.cnf 文件到你项目所在的目录
#2)找到[CA_default],打开 copy_extensionscopy(就是把前面的#去掉)
#3)找到[req],打开 req_extensionsv3_req # Thhe extensions to add to a certificate request
#4)找到[v3_req],添加 subjectAltNamealt_namnes
#5)添加新的标签[alt_names],和标签字段
DNS.1 *.zhiyu.com这个就是对应未来通过zhiyu.com这个域名去访问才能同意相当于是一个安全性的校验客户端发起请求的时候需要携带该域名这就是安全机制校验