REST协议改造gRPC实战

作者: angeChen | 来源:发表于2017-11-28 15:33 被阅读601次

    gRPC 是由 Google 主导开发的 RPC 框架,使用 HTTP/2 协议并用 ProtoBuf 作为序列化工具。

    gRPC官方对REST的声音是:

    • 和REST一样遵循HTTP协议(明确的说是HTTP/2),但是gRPC提供了全双工流
    • 和传统的REST不同的是gRPC使用了静态路径,从而提高性能
    • 用一些格式化的错误码代替了HTTP的状态码更好的标示错误

    背景

    regist 是在微服务架构上再抽出的一层,用于服务注册,心跳机制,服务注销。

    regist 和 微服务架构 之间使用的是 REST 协议进行通信,现需要改造成 gRPC

    • RPC 框架: gRPC

    • 协议:HTTP/2

    • 序列化工具: ProtoBuf

    • 服务端: regist (golang)

    • 客户端 :微服务架构(java)

    一、服务端改造(golang)

    1. protocal buffer安装

    去官网下载 protoc 压缩包,解压后,将 protoc.exe放在 GOPATH\bin目录下面

    2. 安装GoLang protoc 插件

    gRPC-go可以通过golang 的get命令直接安装,非常方便。
    go get -a github.com/golang/protobuf/protoc-gen-go

    3. 定义register.proto文件
    syntax = "proto3";
    package proto;
    
    service Regist {
      rpc Register (ResponseService) returns (RegisterReply) {}
      rpc Deregister (ResponseService) returns (DeregisterReply) {}
    }
    
    message RegisterReply {
      string message = 1;
    }
    
    message DeregisterReply {
      string message = 1;
    }
    
    message ResponseService {
      string id = 1;
      string name = 2;
      string version = 3;
      string address = 4;
      int32 port = 5;
      map<string, string> metadata = 6; 
    }
    
    • syntax = "proto3",声明protobuf版本为3,默认为2。
    • 定义了一个服务 Regist,其中有两个API RegisterRegister
    • 定义3个message为接受和返回的参数。
    4. 生成 register.pb.go 文件

    register.proto文件所在根目录下,执行:
    protoc --go_out=plugins=grpc:. register.proto

    则会在同目录下生成对应的 register.pb.go 文件,相应的服务器端和客户端的GoLang代码。生成的代码中包含了客户端能够进行RPC的方法以及服务器端需要进行实现的接口。

    5.服务端代码改造
    • register.pb.go 文件中提供的服务接口
    type RegistClient interface {
        Register(ctx context.Context, in *ResponseService, opts ...grpc.CallOption) (*RegisterReply, error)
        Deregister(ctx context.Context, in *ResponseService, opts ...grpc.CallOption) (*DeregisterReply, error)
    } 
    
    • 服务端代码实现上面的接口
    func (s *server) Register(ctx context.Context, in *pb.ResponseService) (*pb.RegisterReply, error) {
        // 定义注册的服务,组装 gRPC 传过来的参数
        service := &rp.Service{
            Name:     in.GetName(),
            Version:  in.GetVersion(),
            Metadata: in.GetMetadata(),
            NodeName: nodeName,
            Nodes: []*rp.Node{
                &rp.Node{
                    ID:      in.GetId(),
                    Address: in.GetAddress(),
                    Port:    int(in.GetPort()),
                },
            },
            Endpoints: []*rp.Endpoint{
                &rp.Endpoint{
                    Name:     in.GetName(),
                    Request:  &rp.Value{},
                    Response: &rp.Value{},
                    Metadata: in.GetMetadata(),
                },
            },
        }
        // 调用 consul 注册接口
        return &pb.RegisterReply{}, registry.Register(service, rp.RegisterTTL(time.Duration(ttl)*time.Second))
    }
    

    二、客户端改造(java)

    1. pom.xml文件中添加 maven 依赖
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty</artifactId>
        <version>1.7.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>1.7.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.7.0</version>
    </dependency>
    
    2. pom.xml文件中 配置protobuf maven插件
        <build>
            <extensions>
                <extension>
                    <groupId>kr.motd.maven</groupId>
                    <artifactId>os-maven-plugin</artifactId>
                    <version>1.5.0.Final</version>
                </extension>
            </extensions>
            <plugins>
                <plugin>
                    <groupId>org.xolstice.maven.plugins</groupId>
                    <artifactId>protobuf-maven-plugin</artifactId>
                    <version>0.5.0</version>
                    <configuration>
                        <protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
                        <pluginId>grpc-java</pluginId>
                        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier}</pluginArtifact>
                    </configuration>
                    <executions>
                        <execution> 
                            <goals>
                                <goal>compile</goal>
                                <goal>compile-custom</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
    3. 定义regist.proto文件
    syntax = "proto3";
    package proto;
     
    option java_multiple_files = true;
    option java_package = "com.fiberhome.smartms.grpc";
    option java_outer_classname = "RegistProto";
    
    service Regist {
      rpc Register (ResponseService) returns (RegisterReply) {}
      rpc Deregister (ResponseService) returns (DeregisterReply) {}
    }
    
    message RegisterReply {
      string message = 1;
    }
    
    message DeregisterReply {
      string message = 1;
    }
    
    message ResponseService {
      string id = 1;
      string name = 2;
      string version = 3;
      string address = 4;
      int32 port = 5;
      map<string, string> metadata = 6; 
    }
    
    4. 自动生成java接口代码

    在pom.xml文件根目录中,执行mvn compile(也可试下mvn install),根据.proto文件自动生成一系列的接口文件。

    - 若生成不成功,多试几次

    5.客户端代码改造
    public class ServiceRegistryGrpc implements ServiceRegistry<Registration> {
    
        private static final Logger logger = Logger.getLogger(ServiceRegistryGrpc.class.getName());
    
        private final ManagedChannel channel;
        private final RegistGrpc.RegistBlockingStub blockingStub;
            
        public ServiceRegistryGrpc(String host, int port) {
            channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
            blockingStub = RegistGrpc.newBlockingStub(channel);
        }
    
        public void shutdown() throws InterruptedException {
            channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
        }
    
        @Override
        public void register(Registration reg) {
            Service service = reg.getService();
            ServiceRegistryGrpc client = new ServiceRegistryGrpc("mos", 9999);
            ResponseService request = ResponseService.newBuilder().setId(service.getId()).setName(service.getName())
                    .setVersion(service.getVersion()).setAddress(service.getAddress()).setPort(service.getPort()).build();
            RegisterReply response;
            try {
                response = blockingStub.register(request);
            } catch (StatusRuntimeException e) {
                logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
                return;
            }
            logger.info("Registering service success ");
        }
    }
    
    • public ServiceRegistryGrpc(String host, int port) {},这个函数是构造客户端 连接 服务

    • response = blockingStub.register(request);,调用服务接口

    三、验证

    1. 启动服务端


      服务端
    2. 启动客户端


      客户端
    3. 数据通信成功


      服务端获取客户端 传来的数据
    1. consul注册成功


      attachment服务

    相关文章

      网友评论

        本文标题:REST协议改造gRPC实战

        本文链接:https://www.haomeiwen.com/subject/ohasbxtx.html