使用grpc-server-spring-boot-starter及nacos搭建grpc服务

在上一篇文章《java使用protobuf-maven-plugin的插件编译proto文件》中,我们使用protobuf-maven-plugin已经生成了grpc的调用的库,这篇文章我们将讲解使用SpringCloud及nacos搭建grpc服务。

具体的实现步骤:

1. 先在github下载一个nacos的release版本应用,下载​​​​​​​地址。 解压缩之后,进到nacos目录,执行如下指令启动nacos,这里我们测试,所以启动的是单机服务:

sh ./bin/startup.sh -m standalone

运行成功后在网页访问:http://localhost:8848/nacos,打开后进到nacos登录页面,使用默认账号/密码:nacos/nacos进行登录。

登录成功后,我们可以看到nacos提供了ConfigManagement和ServiceManagement,我们要看的是服务注册中心的ServiceManagement。

2. 我们在上一章lib的工程中,创建三个module,分别为cloud-grpc-provider9090和cloud-grpc-provider9091和cloud-grpc-consumer10020。 前两个提供服务的grpc的provider的服务端, 后面一个consumer为grpc的消费端。项目结构如下:

3. 在父工程的POM文件中添加如下包依赖

 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <java.version>1.8</java.version>
        <jackson.version>2.11.1</jackson.version>
        <protobuf.plugin.version>0.6.1</protobuf.plugin.version>
        <spring.boot.version>2.3.9.RELEASE</spring.boot.version>
        <springcloud.version>Hoxton.SR9</springcloud.version>
        <springcloud.alibaba.version>2.1.0.RELEASE</springcloud.alibaba.version>
        <protobuf.version>3.14.0</protobuf.version>
        <grpc.java.version>1.35.0</grpc.java.version>
        <!--grpc.starter.version>2.11.0.RELEASE</grpc.starter.version-->
        <grpc.starter.version>2.13.1.RELEASE</grpc.starter.version>
    </properties>

    <dependencyManagement>
        <dependencies>
<!--            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${springcloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- jackson-xml -->
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-xml</artifactId>
                <version>${jackson.version}</version>
            </dependency>

            <!-- grpc -->
            <dependency>
                <groupId>net.devh</groupId>
                <artifactId>grpc-client-spring-boot-starter</artifactId>
                <version>${grpc.starter.version}</version>
            </dependency>

            <dependency>
                <groupId>net.devh</groupId>
                <artifactId>grpc-client-spring-boot-autoconfigure</artifactId>
                <version>${grpc.starter.version}</version>
            </dependency>

            <dependency>
                <groupId>net.devh</groupId>
                <artifactId>grpc-server-spring-boot-starter</artifactId>
                <version>${grpc.starter.version}</version>
            </dependency>

            <dependency>
                <groupId>net.devh</groupId>
                <artifactId>grpc-server-spring-boot-autoconfigure</artifactId>
                <version>${grpc.starter.version}</version>
            </dependency>


            <!-- proto -->
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-protobuf</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-stub</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>

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

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-services</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-api</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-context</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-core</artifactId>
                <version>${grpc.java.version}</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

这里我们使用的spring-boot版本与grpc-client-spring-boot-starter和grpc-server-spring-boot-starter使用的版本不同,所以后面我们需要在grpc的starter排除掉默认的spring-boot版本。同时grpc的相关一些库都使用统一的版本。

这里可以看到grpc底层使用的是netty实现的消息通讯

 4. 配置application.yml文件

//provider的application.yml

server:
  port: 8081

grpc:
  server:
    port: 9091
    security:
      enabled: false

spring:
  application:
    name: cloud-grpc-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

# actuator management
management:
  endpoint:
    health:
      show-details: always
  endpoints:
    web:
      exposure:
        include: '*'
//consumer的application.yml

server:
  port: 10020

spring:
  application:
    name: cloud-grpc-comsumber
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

grpc:
  client:
    cloud-grpc-provider:
      enableKeepAlive: true
      keepAliveWithoutCalls: true
      negotiationType: PLAINTEXT
    GLOBAL:
      security:
        client-auth-enabled: false

以上是provider和consumer的application.yml配置文件。 这里我们使用的同一台机器进行测试,所以要注意不同的provider和consumer应用的server的端口和grpc的端口不要相同。
同时在provider和consumer,将grpc的security的enable开关关掉。consumer端要注意的是设置negotiationType的类型为PLAINTEXT

5. provider和consumer引入相应的包

provider的maven引入:

<dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>cn.ckeen</groupId>
            <artifactId>cloud-grpc-lib</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

consumer的maven引入:

 <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>cn.ckeen</groupId>
            <artifactId>cloud-grpc-lib</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>

两个包都引入了lib包,作为客户端和服务端通讯协议。使用nacos作为注册中心,实现负载均衡。

6. provider的service编写

@GrpcService
public class GreeterService extends SimpleGrpc.SimpleImplBase {

    private static Logger log = LoggerFactory.getLogger(GreeterService.class);

    // 引入该参数是为了做负载均衡验证
    @Value("${grpc.server.port}")
    private String serverPort;

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        String message = "server port:" + serverPort + ",Hello " + request.getName();
        final HelloReply.Builder replyBuilder = HelloReply.newBuilder().setMessage(message);
        responseObserver.onNext(replyBuilder.build());
        responseObserver.onCompleted();
        log.info("Returning " +message);

        responseObserver.onError(Status.INVALID_ARGUMENT.withDescription("测试出错").asException());
    }
}

首先使用GrpcService注解来标识服务,该服务继承自proto文件生成的grpc的SimpleGrpc.SimpleImplBase,同时实现了sayHello的方法,这里我们通过responseObserver将结果返回。

7. consumer的消费

consumer端比较简单,直接使用@GrpcClient的注解生成一个SimpleGrpc的Stub,然后进行调用即可

@Service
public class GreeterService {

    @GrpcClient("cloud-grpc-provider")
    private SimpleGrpc.SimpleBlockingStub simpleBlockingStub;

    public String greet(String name) {

        try {
            HelloReply response = simpleBlockingStub.sayHello(HelloRequest.newBuilder().setName(name).build());
            return response.getMessage();
        } catch (final StatusRuntimeException e) {
            return "FAILED with " + e.getStatus().getCode();
        }
    }

}

最终我们可以写一个controller来调用该服务进行测试,实现代码如下:

    @Resource
    private GreeterService greeterService;

    @GetMapping("greeter")
    public String greet(@RequestParam("name")String name){
        String result = greeterService.greet(name);
        return result;
    }

8. 测试验证

先启动两个provider,我们可以在nacos的service list看到两个provider的注册信息:

 启动consumer访问http://localhost:10020/greeter?name=keen可以看到有返回,刷新后端口还有变化

到此我们简单的一个grpc的服务就已经实现了

demo地址: https://github.com/keenw/spring-cloud-grpc-ck

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
grpc-server-spring-boot-starter是一个基于Spring Boot框架的gRPC服务器的启动器。gRPC(Google Remote Procedure Call)是一种高性能的远程过程调用框架,它使用Protocol Buffers作为接口定义语言,并支持多种编程语言。 grpc-server-spring-boot-starter提供了一系列简化配置和集成的功能,使得在Spring Boot应用中启动和配置gRPC服务器变得更加容易。它提供了自动装配的功能,可以根据应用的配置自动创建和启动gRPC服务器。用户只需要在配置文件中设置相应的参数,如服务器的端口号、TLS证书等,即可完成服务器的启动配置。 在使用grpc-server-spring-boot-starter时,用户可以方便地定义服务接口和实现类。通过使用gRPC的接口定义语言(protobuf)定义接口,并生成对应的Java代码。然后,用户只需要在实现类中实现相应的接口方法即可。 在服务器启动后,grpc-server-spring-boot-starter会根据定义的接口和实现类,自动创建相应的gRPC服务,并将其注册到服务器中。当客户端发起远程调用时,服务器会根据接口定义和方法参数,将请求转发给对应的实现类,并返回执行结果给客户端。 grpc-server-spring-boot-starter还支持对gRPC服务器进行拦截器的配置。拦截器可以在请求和响应的过程中拦截和修改消息,用于实现日志记录、鉴权、性能监控等功能。 总之,grpc-server-spring-boot-starter简化了在Spring Boot应用中使用gRPC的配置和集成过程,使得开发者可以更加便捷地构建和部署gRPC服务器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿CKeen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值