项目作者: alextanhongpin

项目描述 :
Load Balancing gRPC with Nginx
高级语言: Go
项目地址: git://github.com/alextanhongpin/grpc-nginx-docker.git
创建时间: 2018-04-10T07:38:23Z
项目社区:https://github.com/alextanhongpin/grpc-nginx-docker

开源协议:

下载


traefik-grpc

gRPC load balancing with Nginx. The README is heavily inspired from nginx docs.

Prerequisite

As gRPC needs HTTP2, we need valid HTTPS certificates on both gRPC Server and Nginx.

Creating Nginx Certificate

The important thing is the subject must be set to nginx, which is the name of the nginx service:

  1. $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./cert/nginx.key -out ./cert/nginx.cert -subj '/CN=nginx'

Nginx Configuration

At last, we configure our Træfik instance to use both self-signed certificates.

  1. user nginx;
  2. worker_processes auto;
  3. worker_rlimit_nofile 10240;
  4. # Leave this empty for now
  5. events {}
  6. http {
  7. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  8. '$status $body_bytes_sent "$http_referer" '
  9. '"$http_user_agent"';
  10. map $http_upgrade $connection_upgrade {
  11. default upgrade;
  12. '' close;
  13. }
  14. upstream grpcservers {
  15. # The docker endpoint of your grpc servers, you can have multiple here
  16. server server1:50051;
  17. server server2:50052;
  18. }
  19. server {
  20. listen 1443 ssl http2;
  21. # Create a certificate that points to the hostname, e.g. nginx for docker
  22. # $ openssl req -nodes -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=nginx'
  23. ssl_certificate /run/secrets/nginx.cert;
  24. ssl_certificate_key /run/secrets/nginx.key;
  25. location /echo.EchoService {
  26. # Replace localhost:50051 with the address and port of your gRPC server
  27. # The 'grpc://' prefix is optional; unencrypted gRPC is the default
  28. grpc_pass grpcs://grpcservers;
  29. }
  30. }
  31. }

gRPC Server Example

  1. // ...
  2. // Read cert and key file
  3. BackendCert, _ := ioutil.ReadFile("./nginx.cert")
  4. BackendKey, _ := ioutil.ReadFile("./nginx.key")
  5. // Generate Certificate struct
  6. cert, err := tls.X509KeyPair(BackendCert, BackendKey)
  7. if err != nil {
  8. log.Fatalf("failed to parse certificate: %v", err)
  9. }
  10. // Create credentials
  11. creds := credentials.NewServerTLSFromCert(&cert)
  12. // Use Credentials in gRPC server options
  13. serverOption := grpc.Creds(creds)
  14. var s *grpc.Server = grpc.NewServer(serverOption)
  15. defer s.Stop()
  16. pb.RegisterGreeterServer(s, &server{})
  17. err := s.Serve(lis)
  18. // ...

gRPC Client Example

  1. // ...
  2. // Read cert file
  3. FrontendCert, _ := ioutil.ReadFile("./frontend.cert")
  4. // Create CertPool
  5. roots := x509.NewCertPool()
  6. roots.AppendCertsFromPEM(FrontendCert)
  7. // Create credentials
  8. credsClient := credentials.NewClientTLSFromCert(roots, "")
  9. // Dial with specific Transport (with credentials)
  10. conn, err := grpc.Dial("nginx:1443", grpc.WithTransportCredentials(credsClient))
  11. if err != nil {
  12. log.Fatalf("did not connect: %v", err)
  13. }
  14. defer conn.Close()
  15. client := pb.NewGreeterClient(conn)
  16. name := "World"
  17. r, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: name})
  18. // ...

Build

If you have not build the docker images, you can execute this command to build it. Yes, you can set it in docker-compose to build the image, but I prefer to separate it.

  1. $ make build-server
  2. $ make build-client

Test

Run this several time to trigger the client. The client is not running a server, so the docker image is not persistent.

The IP changes:

  1. # Start the application
  2. $ docker-compose up -d
  3. # Make the client call the server
  4. $ docker-compose up -d client

Client Response

To view the response from the client:

  1. $ docker logs $(docker ps -a --filter name=client -q)

Output:

  1. 2018/04/10 07:22:46 got res: &echo.EchoResponse{Text:"hello world from f553b776babf"}
  2. 2018/04/10 07:28:52 got res: &echo.EchoResponse{Text:"hello world from c07dec651f40"}
  3. 2018/04/10 07:28:56 got res: &echo.EchoResponse{Text:"hello world from f553b776babf"}

Nginx Response

  1. $ docker logs $(docker ps -a --filter name=nginx -q)

Output:

  1. 172.18.0.2 - - [10/Apr/2018:07:22:46 +0000] "POST /echo.EchoService/Echo HTTP/2.0" 200 36 "-" "grpc-go/1.12.0-dev"
  2. 172.18.0.2 - - [10/Apr/2018:07:28:52 +0000] "POST /echo.EchoService/Echo HTTP/2.0" 200 36 "-" "grpc-go/1.12.0-dev"
  3. 172.18.0.2 - - [10/Apr/2018:07:28:56 +0000] "POST /echo.EchoService/Echo HTTP/2.0" 200 36 "-" "grpc-go/1.12.0-dev"