通过集成第三方starter包, 可以方便快速的集成gRPC到springboot项目中, 项目地址 [https://github.com/yidongnan/grpc-spring-boot-starter](https://github.com/yidongnan/grpc-spring-boot-starter)

  1. <!-- gRPC Server + Client -->
  2. <dependency>
  3. <groupId>net.devh</groupId>
  4. <artifactId>grpc-spring-boot-starter</artifactId>
  5. <version>2.12.0.RELEASE</version>
  6. </dependency>
  7. <!-- gRPC Server only -->
  8. <dependency>
  9. <groupId>net.devh</groupId>
  10. <artifactId>grpc-server-spring-boot-starter</artifactId>
  11. <version>2.12.0.RELEASE</version>
  12. </dependency>
  13. <!-- gRPC Client only -->
  14. <dependency>
  15. <groupId>net.devh</groupId>
  16. <artifactId>grpc-client-spring-boot-starter</artifactId>
  17. <version>2.12.0.RELEASE</version>
  18. </dependency>

服务端

在服务端, 通过 @GrpcService 注解, 自动添加Service到服务端

@GrpcService
public class GreeterImpl extends GreeterGrpc.GreeterImplBase {
    ...
}

客户端

在客户端, 通过 @GrpcClient 注解, 自动注入stub

@Service
public class FooService {
    @GrpcClient("greeter")
    private GreeterGrpc.GreeterBlockingStub stub;

    ...
}

对应的服务地址可能通过配置文件设置:

grpc.client.name.address=static://localhost:9090

__name__ 对应的就是 greeter, 目标地址支持多种schemes. (优先级0 低 - 10 高)

  • static(优先级4): 静态列表, 例如 static://192.168.1.12:8080,10.0.0.1:1234
  • dns (优先级5): 解析并绑定到给定的DNS名称的所有地址, 地址将被缓存, 只有当现有链接被关闭/失败时才会刷新, 例如:dns:///exmple.com
  • discovery(优先级6): 使用Spring cloud的DiscoveryClient去查找合适目标, 使用gRPC_port元数据来确定端口, 否则使用服务端口, 例如: discovery:///service-name
  • self(优先级 0):如果您使用 grpc-server-spring-boot-starter 并且不想指定自己的地址 / 端口,则可以使用 self 关键词作为 scheme 或者 address 。 这对于需要使用随机服务器端口以避免冲突的测试特别有用。 例如:self或self:self
  • in-process:这是一个特殊的方案,将使用 InProcessChannelFactory 来替代原有正常的 ChannelFactory。 并使用它连接到 InProcessServer。 例如:in-process:foobar
  • custom: 您可以通过 Java 的 ServiceLoader 或从 Spring 的应用上下文中选择要自定义的 NameResolverProvider ,并将其注册到 NameResolverRegistry 上.

如果没有配置地址, 它将按下面的方式进行猜测:

  • 首先尝试使用名称 (<name>)
  • 如果配置了默认方案, 它将尝试下一个(<scheme>:<name>)
  • 然后使用NameResolver.Factory委托的默认方案 discovery -> dns -> static

我们可以集成Eurake, Nacos 等注册中心, 将服务以服务名的形式注册到注册中心, 客户端通过 name 实现discovery的方案.

客户端安全

gRPC默认使用TLS连接服务端, 如果要修改,可以通过配置:

grpc.client.name.negotiationType=PLAINTEXT

或全局:

grpc.client.GLOBAL.negotiationType=PLAINTET

如果要启用TLS传输, 对依赖有要求 classpath上有兼容的SSL/TLS实现

  • io.grpc:grpc-netty-shaded
  • io.grpc:grpc-netty, 还需要额外添加netty-tcnative-boringssl-static依赖, 需使用 (gprc-java的netty安全部分表中列出安全相同(兼容)的版本)
  • 带有私钥的证书

    注: io.grpc:grpc-netty-shaded 是集成netty所必需的依赖, 主要解决netty版本冲突的问题, 如果采用io.grpc:grpc-netty, 则需要按要选择合适的netty其它依赖

生成一个自签名的证书

openssl req -x509 -nodes -subj "//CN=localhost" -newkey rsa:4096 -sha256 -keyout server.key -out server.crt -days 3650

服务端配置

grpc.server.security.enabled=true
grpc.server.security.certificateChain=file:certificates/server.crt
grpc.server.security.privateKey=file:certificates/server.key
#grpc.server.security.privateKeyPassword=MyStrongPassword

更多配置可查看文档