gRPC Spring Boot Starter 正在参加 2020 年度 OSC 中国开源项目评选,请投票支持!
gRPC Spring Boot Starter 在 2020 年度 OSC 中国开源项目评选 中已获得 {{ projectVoteCount }} 票,请投票支持!
投票让它出道
已投票
授权协议: MIT
开发语言: Java
操作系统: 跨平台
收录时间: 2017-02-27
提 交 者: yidongnan

gRPC 框架的 Spring Boot 启动器模块

项目主页:grpc-spring-boot-starter

特点

  • 使用@ GrpcService自动创建并运行一个 gRPC 服务,内嵌在 spring-boot 应用中

  • 使用@ GrpcClient自动创建和管理你的channelstub

  • 支持 Spring Cloud(向 Consul 或 Eureka 或 Nacos 注册服务并获取gRPC服务信息)

  • 支持 Spring Sleuth 进行链路跟踪(需要单独引入 brave-instrumentation-grpc)

  • 支持对 server、client 分别设置全局拦截器或单个的拦截器

  • 支持 Spring-Security

  • 支持 metric (micrometer / actuator)

  • 可以使用 (non-shaded) grpc-netty

版本

2.x.x.RELEASE 支持 Spring Boot 2.1+ & Spring Cloud Greenwich。

最新的版本:2.5.0.RELEASE

(使用 2.4.0.RELEASE 版本可以支持 Spring Boot 2.0.X & Spring Cloud Finchley).

1.x.x.RELEASE 支持 Spring Boot 1 & Spring Cloud Edgware 、Dalston、Camden。

最新的版本:1.4.2.RELEASE

注意: 此项目也可以在没有 Spring-Boot 的场景下使用,但需要手动的配置相关的 bean。

使用方式

gRPC server + client

如果使用的是 Maven,添加如下依赖

<dependency>
  <groupId>net.devh</groupId>
  <artifactId>grpc-spring-boot-starter</artifactId>
  <version>2.5.0.RELEASE</version>
</dependency>

如果使用的 Gradle,添加如下依赖

dependencies {
  compile 'net.devh:grpc-spring-boot-starter:2.5.0.RELEASE'
}

gRPC 服务端

如果使用的是 Maven,添加如下依赖

<dependency>
  <groupId>net.devh</groupId>
  <artifactId>grpc-server-spring-boot-starter</artifactId>
  <version>2.5.0.RELEASE</version>
</dependency>

如果使用的 Gradle,添加如下依赖

dependencies {
  compile 'net.devh:grpc-server-spring-boot-starter:2.5.0.RELEASE'
}

实现 gRPC server 的业务逻辑,并使用 @GrpcService 注解

@GrpcService
public class GrpcServerService extends GreeterGrpc.GreeterImplBase {

    @Override
    public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
        HelloReply reply = HelloReply.newBuilder().setMessage("Hello ==> " + req.getName()).build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }
}

设置 gRPC 的 host 跟 port ,默认的监听的 port 是 9090。其他配置属性可以参考 settings。 所有的配置属性在 server 中使用需增加 grpc.server. 的前缀

服务端配置属性示例

grpc.server.port=9090
grpc.server.address=0.0.0.0
#grpc.server.inProcessName=test

对 Server 进行自定义

当前项目同样支持对 ServerBuilder 的自定义修改,需要在创建的过程中使用 GrpcServerConfigurer beans。

@Bean
public GrpcServerConfigurer keepAliveServerConfigurer() {
  return serverBuilder -> {
    if (serverBuilder instanceof NettyServerBuilder) {
      ((NettyServerBuilder) serverBuilder)
          .keepAliveTime(30, TimeUnit.SECONDS)
          .keepAliveTimeout(5, TimeUnit.SECONDS)
          .permitKeepAliveWithoutCalls(true);
    }
  };
}

Server-Security

支持使用 Spring-Security 加密你的 gRPC 应用。你只需要添加 Spring-Security(core 或者 config)依赖,然后根据需要再增加加密的配置

首先需要选择一个认证方案

  • BasicAuth(基础认证)

    @Bean
    AuthenticationManager authenticationManager() {
        final List<AuthenticationProvider> providers = new ArrayList<>();
        providers.add(...); // Possibly DaoAuthenticationProvider
        return new ProviderManager(providers);
    }
    
    @Bean
    GrpcAuthenticationReader authenticationReader() {
        final List<GrpcAuthenticationReader> readers = new ArrayList<>();
        readers.add(new BasicGrpcAuthenticationReader());
        return new CompositeGrpcAuthenticationReader(readers);
    }
  • Bearer Authentication (OAuth2/OpenID-Connect)

    @Bean
    AuthenticationManager authenticationManager() {
        final List<AuthenticationProvider> providers = new ArrayList<>();
        providers.add(...); // Possibly JwtAuthenticationProvider
        return new ProviderManager(providers);
    }
    
    @Bean
    GrpcAuthenticationReader authenticationReader() {
        final List<GrpcAuthenticationReader> readers = new ArrayList<>();
        readers.add(new BearerAuthenticationReader(accessToken -> new BearerTokenAuthenticationToken(accessToken)));
        return new CompositeGrpcAuthenticationReader(readers);
    }

    你可能还想定义自己的 GrantedAuthoritiesConverter ,将权限和角色的信息映射到 Spring Security 的 GrantedAuthority 中

  • Certificate Authentication(证书认证)

    @Bean
    AuthenticationManager authenticationManager() {
        final List<AuthenticationProvider> providers = new ArrayList<>();
        providers.add(new X509CertificateAuthenticationProvider(userDetailsService()));
        return new ProviderManager(providers);
    }
    
    @Bean
    GrpcAuthenticationReader authenticationReader() {
        final List<GrpcAuthenticationReader> readers = new ArrayList<>();
        readers.add(new SSLContextGrpcAuthenticationReader());
        return new CompositeGrpcAuthenticationReader(readers);
    }

    相关的配置属性如下:

    grpc.server.security.enabled=true
    grpc.server.security.certificateChain=file:certificates/server.crt
    grpc.server.security.privateKey=file:certificates/server.key
    grpc.server.security.trustCertCollection=file:certificates/trusted-clients-collection
    grpc.server.security.clientAuth=REQUIRE
  • 使用 CompositeGrpcAuthenticationReader 类链式的调用多个认证方案

  • 自定义认证方式(继承并实现 GrpcAuthenticationReader 类)

如何去保护你的这些服务

  • 使用 Spring-Security 的注解

    @Configuration
    @EnableGlobalMethodSecurity(proxyTargetClass = true, ...)
    public class SecurityConfiguration {

    如果你想使用 Spring Security 相关的注解的话,proxyTargetClass 属性是必须的! 但是你会受到一条警告,提示 MyServiceImpl#bindService() 方式是用 final 进行修饰的。 这条警告目前无法避免,但它是安全的,可以忽略它。

  • 手动配置

    @Bean
    AccessDecisionManager accessDecisionManager() {
        final List<AccessDecisionVoter<?>> voters = new ArrayList<>();
        voters.add(new AccessPredicateVoter());
        return new UnanimousBased(voters);
    }
    
    @Bean
    GrpcSecurityMetadataSource grpcSecurityMetadataSource() {
        final ManualGrpcSecurityMetadataSource source = new ManualGrpcSecurityMetadataSource();
        source.set(MyServiceGrpc.getSecureMethod(), AccessPredicate.hasRole("ROLE_USER"));
        source.setDefault(AccessPredicate.permitAll());
        return source;
    }

gRPC 客户端

如果使用的是 Maven,添加如下依赖

<dependency>
  <groupId>net.devh</groupId>
  <artifactId>grpc-client-spring-boot-starter</artifactId>
  <version>2.5.0.RELEASE</version>
</dependency>

如果使用的 Gradle,添加如下依赖

dependencies {
  compile 'net.devh:grpc-client-spring-boot-starter:2.5.0.RELEASE'
}

这里有三种方式去或得一个gRPC server的连接

  • 使用 grpcChannelFactory.createChannel(serverName) 去创建一个 Channel,并创建一个自己的 gRPC stub.

    @Autowired
    private GrpcChannelFactory grpcChannelFactory;
    
    private GreeterGrpc.GreeterBlockingStub greeterStub;
    
    @PostConstruct
    public void init() {
        Channel channel = grpcChannelFactory.createChannel("gRPC server name");
        greeterStub = GreeterGrpc.newBlockingStub(channel);
    }
  • 通过在 Channel 类型的字段上加入 @GrpcClient(serverName) 注解,并创建一个自己的 gRPC stub.

    • 不需要使用 @Autowired 或者 @Inject 来进行注入
    @GrpcClient("gRPC server name")
    private Channel channel;
    
    private GreeterGrpc.GreeterBlockingStub greeterStub;
    
    @PostConstruct
    public void init() {
        greeterStub = GreeterGrpc.newBlockingStub(channel);
    }
  • 直接将 @GrpcClient(serverName) 注解加在调用客户端的 stub 上

    • 不需要使用 @Autowired 或者 @Inject 来进行注入
    @GrpcClient("gRPC server name")
    private GreeterGrpc.GreeterBlockingStub greeterStub;

注意: 你可以为多个 channels 和多个不同的 stubs 使用相同的 serverName (除非他们拦截器不一样).

然后你可以直接向服务端发起请求,如下:

HelloReply response = stub.sayHello(HelloRequest.newBuilder().setName(name).build());

可以单独为每一个 client 配置对应的 address 但在某些情况下,你可以调整默认的配置。 你可以通过 NameResolver.Factory beans 去自定义默认的 url 映射,如果你没有配置这个 bean,那将会按照下面的方式进行解析:

  • 如果存在一个 DiscoveryClient 的 bean,这时会使用 client name 去注册中心上进行获取对应服务的 address
  • 否则 client 端将使用 localhost 和 9090 端口

其他的配置属性参考 settings,所有的配置文件在 client 端使用时需要增加 grpc.client.(serverName).的前缀

你也可以配置多个目标地址,请求时会自动使用负载均衡

  • static://127.0.0.1:9090,[::1]:9090

你也可以使用服务发现去获取目标地址(要求一个 DiscoveryClient bean)

  • discovery:///my-service-name

此外,你也可以使用 DNS 的方式去获取目标地址

  • dns:///example.com

同时,你也可以使用如下方式直接进程内访问

  • in-process:test

它会通过DNS将域名解析出所有真实的 IP 地址,通过使用这些真实的IP地址去做负载均衡。 需要注意的是 grpc-java 出于性能的考虑对 DNS 返回的结果做缓存。 有关这些和其他原生支持的 NameResolverProviders 参考官方文档 grpc-java sources

客户端配置属性示例

grpc.client.GLOBAL.enableKeepAlive=true

grpc.client.(gRPC server name).address=static://localhost:9090
# Or
grpc.client.myName.address=static://localhost:9090

GLOBAL 是一个特殊的常量,它可以用于对所有 Client 统一的设置属性。 属性覆盖的顺序:Client单独的属性 > GLOBAL的属性 > 默认的属性

自定义 Client

This library also supports custom changes to the ManagedChannelBuilder and gRPC client stubs during creation by creating GrpcChannelConfigurer and StubTransformer beans. 当前项目支持对 ManagedChannelBuilder 的自定义,在 gRPC client stub创建的过程中,通过使用 GrpcChannelConfigurer 或 StubTransformer bean 来完成自定义操作

@Bean
public GrpcChannelConfigurer keepAliveClientConfigurer() {
  return (channelBuilder, name) -> {
    if (channelBuilder instanceof NettyChannelBuilder) {
      ((NettyChannelBuilder) channelBuilder)
          .keepAliveTime(15, TimeUnit.SECONDS)
          .keepAliveTimeout(5, TimeUnit.SECONDS);
    }
  };
}

@Bean
public StubTransformer authenticationStubTransformer() {
  return (clientName, stub) -> stub.withCallCredentials(grpcCredentials(clientName));
}

客户端认证

注意: 以下列出的一些方法仅仅适用于通过注入得到的 stubs,如果你通过注入 Channel,手动的在去创建 stubs,这就需要你自己手动的 去配置凭证。然而你同样能从目前所提供的一些辅助类方法中收益。

客户端有许多不同的认证方式,我们只需定义一个类型为 CallCredentials 的 bean,它会自动作用于身份验证。目前通过一些辅助方法可以支持 下列的认证方式:

  • BasicAuth

    @Bean
    CallCredentials grpcCredentials() {
      return CallCredentialsHelper.basicAuth(username, password);
    }
  • Bearer Authentication (OAuth2, OpenID-Connect)

    @Bean
    CallCredentials grpcCredentials() {
      return CallCredentialsHelper.bearerAuth(token);
    }
  • Certificate Authentication

    需要一些配置属性:

    #grpc.client.test.security.authorityOverride=localhost
    #grpc.client.test.security.trustCertCollection=file:certificates/trusted-servers-collection
    grpc.client.test.security.clientAuthEnabled=true
    grpc.client.test.security.certificateChain=file:certificates/client.crt
    grpc.client.test.security.privateKey=file:certificates/client.key
    
  • 为每个 client 使用不同的认证

    通过定义一个 StubTransformer bean 来代替原有的 CallCredentials bean

    @Bean
    StubTransformer grpcCredentialsStubTransformer() {
      return CallCredentialsHelper.mappedCredentialsStubTransformer(
          Map.of(
              clientA, callCredentialsAC,
              clientB, callCredentialsB,
              clientC, callCredentialsAC));
    }

    注意: 如果你配置了 CallCredentials bean,然后再使用 StubTransformer 的话可能会造成冲突。

使用 (non-shaded)grpc-netty

当前项目目前支持 grpc-netty 和 grpc-netty-shaded。 使用 grpc-netty-shaded 可以防止 grpc 跟 netty 版本的兼容性问题。

注意: 如果 grpc-netty-shaded 已经存在于 classpath 中, 那么将优先使用 shaded-netty

如果你使用的Maven,你可以使用如下的配置:

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty</artifactId>
    <version>${grpcVersion}</version>
</dependency>

<!-- For both -->
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-spring-boot-starter</artifactId>
    <version>...</version>
    <exclusions>
        <exclusion>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- For the server (only) -->
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-server-spring-boot-starter</artifactId>
    <version>...</version>
    <exclusions>
        <exclusion>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- For the client (only) -->
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-client-spring-boot-starter</artifactId>
    <version>...</version>
    <exclusions>
        <exclusion>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
        </exclusion>
    </exclusions>
</dependency>

如果你使用的 Gradle,你可以使用如下的配置:

compile "io.grpc:grpc-netty:${grpcVersion}"

compile 'net.devh:grpc-spring-boot-starter:...' exclude group: 'io.grpc', module: 'grpc-netty-shaded' // For both
compile 'net.devh:grpc-client-spring-boot-starter:...' exclude group: 'io.grpc', module: 'grpc-netty-shaded' // For the client (only)
compile 'net.devh:grpc-server-spring-boot-starter:...' exclude group: 'io.grpc', module: 'grpc-netty-shaded' // For the server (only)
展开阅读全文

代码

的 Gitee 指数为
超过 的项目

gRPC Spring Boot Starter 的相关博客

集成Spring-Boot与gRPC,grpc-spring-boot-starter

项目地址:grpc-spring-boot-starter grpc是一个出身名门的RPC框架,性能高,灵活度高,支持多语言。 支持多语言,如果你的项...

【行业资讯】gRPC Spring Boot Starter 2.10.0 正式发布

gRPC Spring Boot Starter 2.10.0 正式发布了,gRPC Spring Boot Starter 项目是一个 gRPC 的 Spring Boot 模块。通过在 Spri...

spring boot 整合 Grpc 说明

<!-- 用到的 maven 依赖 --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId>...

gRPC

gRPC https://grpc.io/ http://grpc.github.io/ https://github.com/grpc/grpc https://github.com/grpc/grpc-java protobuf ...

grpc

更多请参考:https://grpc.io/docs/quickstart 一、准备工作 1. grpc编译安装 >yum install -y gcc-c++ autoconf libtool >yu...

Grpc

Channel-stub-method调用 ClinetCallImpl:客户端调用类,主要是start()方法; 其中包含了CallOptions对象,设置相关参数; Grp...

grpc-gateway--支持grpc和restful

The grpc-gateway is a plugin of the Google protocol buffers compiler protoc. It reads protobuf service definitions an...

gRPC在Spring Cloud中的应用

1、前言 在微服务开发中,服务间的调用一般有两种方式:Feign、RestTemplate,但在实际使用过程中,尤其是Feign,存在各种限制...

gRPC Spring Boot Starter 的相关问答

评论 (1)

加载中
好项目…
2019/08/12 10:43
回复
举报
更多评论
1 评论
70 收藏
分享
返回顶部
顶部