已发表的技术专栏
0 grpc-go、protobuf、multus-cni 技术专栏 总入口
1 grpc-go 源码剖析与实战 文章目录
2 Protobuf介绍与实战 图文专栏 文章目录
3 multus-cni 文章目录(k8s多网络实现方案)
4 grpc、oauth2、openssl、双向认证、单向认证等专栏文章目录)
本篇文章将介绍如何使得NGINX作为负载均衡器,代理grpc客户端的请求;
本小节所需的资料,已经上传到百度网盘
(链接: https://pan.baidu.com/s/1za02qnUII78n-XhlrLf7RA 密码: 3tok)
1、整体流程介绍 |
整体流程图,如下所示:
红色线,表示grpc客户端最终从三个tcp链接中选择的链接作为帧的传输链路。
环境说明:
在Mac上:
主要流程说明:
在grpc客户端里采用默认的解析器passthrough,默认pickfirst平衡器;
当grpc客户端向NGINX发起请求,NGINX收到请求后,会从3个地址里根据负载均衡策略选择一个地址(如上图中红色实线),进行rpc通信。
也就是说,grpc客户端并没有跟grpc服务器端进行直连,而是通过NGINX进行里代理转发。
接下来,直接看测试用例
2、参考实例: |
2.1、grpc服务器端代码 |
grpc服务器代码,跟以前的测试用例,区别不大:
1.package main
2.import (
//---省略导入代码
3.)
4.const (
5. port = ":50051"
6.)
7.const (
8. timestampFormat = time.StampNano
9. streamingCount = 10
10.)
11.var DataFrameNum int8
12.var PingNum int8
13.// server1 is used to implement helloworld.GreeterServer.
14.// 实现了所有接口sayhello1,sayHello2,sayHello3,sayHello4
15.// server1 包含pb.UnimplementedGreeterServer, 相当于继承,
16.// 覆写了 sayhello1,sayHello2,sayHello3,sayHello4
17.type server struct {
18. pb.UnimplementedGreeterServer
19.}
20.// SayHello implements helloworld.GreeterServer
21.func (s *server) SayHello1(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
22. return &pb.HelloReply{Message: "---From Server---gprc--nginx---50051---" + in.GetName()}, nil
23.}
24.func main() {
25. lis, err := net.Listen("tcp", port)
26. if err != nil {
27. log.Errorf("failed to listen: %v", err)
28. }
29. s := grpc.NewServer()
30. // 将helloworld_grpc.pb.go文件里_Greeter_serviceDesc声明的服务,注册到grpc服务里
31. pb.RegisterGreeterServer(s, &server{})
32. if err := s.Serve(lis); err != nil {
33. log.Errorf("failed to serve: %v", err)
34. }
35.}
2.2、grpc客户端测试用例 |
1.package main
2.import (
//---省略导入代码
3.)
4.const (
5. // address, 是nginx的地址
6. address = "10.211.55.10:8081"
7. defaultName = "----h2c-------"
8.)
9.const (
10. timestampFormat = time.StampNano // "Jan _2 15:04:05.000"
11. streamingCount = 10
12.)
13.func main() {
14. reWG := &sync.WaitGroup{}
15. for i:=0; i < 2; i++ {
16. reWG.Add(1)
17. go request(reWG, int8(i))
18. }
19. reWG.Wait()
20.}
21.func request(wg *sync.WaitGroup, index int8) {
22. // Set up a connection to the server.
23. conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
24. if err != nil {
25. log.Errorf("did not connect: %v", err)
26. }
27. defer conn.Close()
28. // 根据ClientConn, 创建GreeterClient
29. c := pb.NewGreeterClient(conn)
30. // Contact the server and print out its response.
31. name := defaultName
32. if len(os.Args) > 1 {
33. name = os.Args[1]
34. }
35. ctx, cancel := context.WithTimeout(context.Background(), time.Second * 10 )
36. defer cancel()
37. for i :=0; i<1;i++{
38. msg, err := c.SayHello1(ctx, &pb.HelloRequest{Name: name})
39. if err != nil {
40. panic(fmt.Sprintf("----------==============>could not greet: %v", err))
41. }
42. log.Infof("------------------>------------->Greeting: %s", msg.GetMessage())
43. }
44. wg.Done()
45.}
2.3、NGINX启动说明 |
NGINX是从1.13.10开始支持gRPC 协议的;(https://www.nginx.com/blog/nginx-1-13-10-grpc/)
2.3.1、NGINX镜像构建 |
虽然NGINX支持grpc协议了,但是,需要重新编译,添加相应的模块才行;
下面了提供了Dockerfile:
FROM gcc:latest
ADD nginx-1.16.0.tar.gz /usr/local
RUN mkdir -p /usr/local/nginx
RUN cd /usr/local/nginx-1.16.0 \
&& ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_gzip_static_module --with-http_v2_module \
&& make \
&& make install
ENV PATH $PATH:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
通过下面的命令,构建镜像:
docker build -t nginx-gcc:1.16.0 .
2.3.2、NGINX配置文件 |
nginx.conf全部内容如下:
http {
upstream lb {
server 192.168.43.214:50051;
server 192.168.43.214:50052;
server 192.168.43.214:50053;
}
server {
listen 80 http2;
location / {
grpc_pass grpc://lb;
autoindex on;
index index.html index.htm;
}
}
}
events {
worker_connections 1024;
}
2.3.3、容器运行NGINX启动脚本 |
为了测试方便,提供了一个启动脚本:
#!/bin/bash
docker stop nginx-grpc
docker rm nginx-grpc
docker run -it -d --name nginx-grpc -p 8081:80 -v /root/grpc/nginx.conf:/usr/local/nginx/conf/nginx.conf nginx-gcc:1.16.0
注意:
如果使用此脚本,需要修改/root/grpc/nginx.conf的位置,改成实际路径
到目前为止,grpc+nginx方案,介绍完成;
3、总结 |
本文使用NGINX作为独立进程式负载均衡器,来负责grpc客户端的请求转发;
也就是说,grpc客户端跟grpc服务器端并不是直连式通信。
NGINX提供了负载均衡的能力,从众多的grpc服务器地址中根据设置的策略(如轮询策略),进行流量的转发。
下一篇文章
grpc+consul+自定义平衡器weight-balancer方案介绍