使用spring boot集成grpc
创始人
2024-06-02 05:56:58
0

目录

创建maven父工程spring-boot-grpc

创建模块spring-boot-grpc-lib

创建模块local-server(gRPC服务端)

创建模块local-client(gRPC客户端)


创建maven父工程spring-boot-grpc

创建springboot项目,勾选springboot-web即可


4.0.0pomspring-boot-grpc-liblocal-serverlocal-clientorg.springframework.bootspring-boot-starter-parent2.5.6 com.chenjspring-boot-grpc0.0.1-SNAPSHOTspring-boot-grpcDemo project for Spring Boot1.8org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtest

创建模块spring-boot-grpc-lib

在父工程spring-boot-grpc下新建maven模块,名为spring-boot-grpc-lib


spring-boot-grpccom.chenj0.0.1-SNAPSHOT4.0.0spring-boot-grpc-libUTF-81.81.8io.grpcgrpc-netty-shaded1.37.0io.grpcgrpc-protobuf1.37.0io.grpcgrpc-stub1.37.0 org.apache.tomcatannotations-api6.0.53providedkr.motd.mavenos-maven-plugin1.6.2org.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:1.37.0:exe:${os.detected.classifier}compilecompile-custom

在spring-boot-grpc-lib模块的src/main/proto目录下新增名为helloworld.proto的文件,这里面定义了一个gRPC服务,里面含有一个接口,并且还有这个接口的入参和返回结果的定义:

syntax = "proto3";option java_multiple_files = true;
option java_package = "com.chenj.grpc.lib";
option java_outer_classname = "HelloWorldProto";// The greeting service definition.
service Simple {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.
message HelloRequest {string name = 1;
}// The response message containing the greetings
message HelloReply {string message = 1;
}

proto文件已经做好,接下来要根据这个文件来生成Java代码

SimpleGrpc里面有抽象类SimpleImplBase,制作gRPC服务的时候需要继承该类,另外,如果您要远程调用gRPC的sayHello接口,就会用到SimpleGrpc类中的SimpleStub类,其余的HelloReply、HelloRequest这些则是入参和返回的数据结构定义

创建模块local-server(gRPC服务端)

在父工程下面新建名为local-server的springboot模块,

gRPC 服务端使用一下命令添加 Maven 依赖项

net.devhgrpc-server-spring-boot-starter2.12.0.RELEASE

依赖上面的spring-boot-grpc-lib模块

com.chenjspring-boot-grpc-lib0.0.1-SNAPSHOT

完整的pom.xml文件


4.0.0spring-boot-grpccom.chenj0.0.1-SNAPSHOTcom.chenjlocal-server0.0.1-SNAPSHOTlocal-serverDemo project for Spring Boot1.8net.devhgrpc-server-spring-boot-starter2.12.0.RELEASEcom.chenjspring-boot-grpc-lib0.0.1-SNAPSHOTorg.projectlomboklombok

springboot应用,配置文件内容如下:

spring:application:name: spring-boot-grpc-server
# gRPC有关的配置,这里只需要配置服务端口号
grpc:server:port: 9898
server:port: 8080

新建拦截类LogGrpcInterceptor.java,每当gRPC请求到来后该类会先执行,这里是将方法名字在日志中打印出来,您可以对请求响应做更详细的处理:

package com.chenj.springbootgrpcserver.interceptor;import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import lombok.extern.slf4j.Slf4j;@Slf4j
public class LogGrpcInterceptor implements ServerInterceptor {@Overridepublic  ServerCall.Listener interceptCall(ServerCall serverCall, Metadata metadata,ServerCallHandler serverCallHandler) {log.info(serverCall.getMethodDescriptor().getFullMethodName());return serverCallHandler.startCall(serverCall, metadata);}
}

为了让LogGrpcInterceptor可以在gRPC请求到来时被执行,需要做相应的配置,如下所示,在普通的bean的配置中添加注解即可:

package com.chenj.springbootgrpcserver.config;import com.chenj.springbootgrpcserver.interceptor.LogGrpcInterceptor;
import io.grpc.ServerInterceptor;
import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
import org.springframework.context.annotation.Configuration;@Configuration(proxyBeanMethods = false)
public class GlobalInterceptorConfiguration {@GrpcGlobalServerInterceptorServerInterceptor logServerInterceptor() {return new LogGrpcInterceptor();}
}

应用启动类很简单:

package com.chenj.springbootgrpcserver;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootGrpcServerApplication {public static void main(String[] args) {SpringApplication.run(SpringBootGrpcServerApplication.class, args);}}

接下来是最重要的service类,gRPC服务在此处对外暴露出去,完整代码如下

package com.chenj.springbootgrpcserver.service;import com.chenj.grpc.lib.HelloReply;
import com.chenj.grpc.lib.HelloRequest;
import com.chenj.grpc.lib.SimpleGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;import java.util.Date;@GrpcService
public class GrpcServerService extends SimpleGrpc.SimpleImplBase {@Overridepublic void sayHello(HelloRequest request,StreamObserver responseObserver) {HelloReply reply = HelloReply.newBuilder().setMessage("你好, " + request.getName() + ", " + new Date()).build();responseObserver.onNext(reply);responseObserver.onCompleted();}
}

上述GrpcServerService.java中有几处需要注意:

是使用@GrpcService注解,再继承SimpleImplBase,这样就可以借助grpc-server-spring-boot-starter库将sayHello暴露为gRPC服务;

SimpleImplBase是前文中根据proto自动生成的java代码,在spring-boot-grpc-lib模块中;

sayHello方法中处理完毕业务逻辑后,调用HelloReply.onNext方法填入返回内容;

调用HelloReply.onCompleted方法表示本次gRPC服务完成;

至此,gRPC服务端编码就完成了,咱们接着开始客户端开发

创建模块local-client(gRPC客户端)

在父工程grpc-turtorials下面新建名为local-client的模块

gRPC客户端使用一下命令添加 Maven 依赖项:

net.devhgrpc-client-spring-boot-starter2.12.0.RELEASE

依赖上面的spring-boot-grpc-lib模块

com.chenjspring-boot-grpc-lib0.0.1-SNAPSHOT

完整的pom.xml文件


4.0.0spring-boot-grpccom.chenj0.0.1-SNAPSHOTcom.chenjlocal-client0.0.1-SNAPSHOTlocal-clientDemo project for Spring Boot1.8net.devhgrpc-client-spring-boot-starter2.12.0.RELEASEcom.chenjspring-boot-grpc-lib0.0.1-SNAPSHOTorg.springframework.bootspring-boot-maven-plugin

应用配置文件src/main/resources/application.yml,注意address的值就是gRPC服务端的信息,我这里local-server和local-client在同一台电脑上运行,请您根据自己情况来设置:

server:port: 8088
spring:application:name: local-clientgrpc:client:# gRPC配置的名字,GrpcClient注解会用到local-grpc-server:# gRPC服务端地址address: 'static://127.0.0.1:9898'enableKeepAlive: truekeepAliveWithoutCalls: truenegotiationType: plaintext

新建拦截类LogGrpcInterceptor,与服务端的拦截类差不多,不过实现的接口不同:

package com.chenj.springbootgrpcclient.interceptor;import io.grpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class LogGrpcInterceptor implements ClientInterceptor {private static final Logger log = LoggerFactory.getLogger(LogGrpcInterceptor.class);@Overridepublic  ClientCall interceptCall(MethodDescriptor method,CallOptions callOptions, Channel next) {log.info(method.getFullMethodName());return next.newCall(method, callOptions);}
}

为了让拦截类能够正常工作,即发起gRPC请求的时候被执行,需要新增一个配置类:

package com.chenj.springbootgrpcclient.config;import com.chenj.springbootgrpcclient.interceptor.LogGrpcInterceptor;
import io.grpc.ClientInterceptor;
import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;@Order(Ordered.LOWEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
public class GlobalClientInterceptorConfiguration {@GrpcGlobalClientInterceptorClientInterceptor logClientInterceptor() {return new LogGrpcInterceptor();}
}

启动类:

package com.chenj.springbootgrpcclient;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootGrpcClientApplication {public static void main(String[] args) {SpringApplication.run(SpringBootGrpcClientApplication.class, args);}}

接下来是最重要的服务类GrpcClientService

package com.chenj.springbootgrpcclient.service;import com.chenj.grpc.lib.HelloReply;
import com.chenj.grpc.lib.HelloRequest;
import com.chenj.grpc.lib.SimpleGrpc;
import io.grpc.StatusRuntimeException;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;@Service
public class GrpcClientService {@GrpcClient("local-grpc-server")private SimpleGrpc.SimpleBlockingStub simpleStub;public String sendMessage(final String name) {try {final HelloReply response = this.simpleStub.sayHello(HelloRequest.newBuilder().setName(name).build());return response.getMessage();} catch (final StatusRuntimeException e) {return "FAILED with " + e.getStatus().getCode().name();}}
}

上述GrpcClientService类有几处要注意的地方:

用@Service将GrpcClientService注册为spring的普通bean实例;

用@GrpcClient修饰SimpleBlockingStub,这样就可以通过grpc-client-spring-boot-starter库发起gRPC调用,被调用的服务端信息来自名为local-grpc-server的配置;

SimpleBlockingStub来自前文中根据helloworld.proto生成的java代码;

SimpleBlockingStub.sayHello方法会远程调用local-server应用的gRPC服务;

为了验证gRPC服务调用能否成功,再新增个web接口,接口内部会调用GrpcClientService.sendMessage,这样咱们通过浏览器就能验证gRPC服务是否调用成功了:

package com.chenj.springbootgrpcclient.controller;import com.chenj.springbootgrpcclient.service.GrpcClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class GrpcClientController {@Autowiredprivate GrpcClientService grpcClientService;@RequestMapping("/")public String printMessage(@RequestParam(defaultValue = "will") String name) {return grpcClientService.sendMessage(name);}
}

相关内容

热门资讯

敦煌曲子戏:让千年文脉奏响时代...   敦煌,这座沉淀着千年文明的丝路重镇,不仅以莫高窟的壁画、鸣沙山的驼铃诉说着历史沧桑,更在当代文艺...
大学生打零工居然成为4家公司高... 转自:北京时间 【#大学生打零工居然成为4家公司高管#】...
店员周末忙哭,茶百道股价今天大...   “太疯狂了,全国人民都在熬夜点外卖。喝不完,根本喝不完。”不少网友感叹。与之相呼应的是奶茶店的店...
夏厦精密:公司目前主要应用于机... 每经AI快讯,有投资者在投资者互动平台提问:2025年机器人结构件订单是否覆盖全年产能 60%?与客...
杨昆会见国家电力投资集团党组成... (转自:电力国际汇epintl)  7月4日,中国电力企业联合会党委书记、常务副理事长杨昆在本部会见...
18岁男生庆祝与女友同居,表演... 近日,澳大利亚昆士兰州,18岁少年桑尼·布伦德尔在庆祝与女友开始同居生活时,因表演后空翻失误导致头部...
焦点访谈丨跨区域招聘、开设微专... 本文转自【央视新闻客户端】2025年全国高校毕业生预计达1222万人。当年年刷新的毕业生数字和经济转...
绿联推出“充电宝以旧换新”计划... 充电宝品牌绿联7月6日在官方微博发布消息称,即日起至8月5日,绿联推出“充电宝以旧换新计划”,持20...
盘面低开低走 今日广西现货市场... YNTW.COM 今日(7月7日)早盘郑商所白糖期货低开低走,上午主力2509合约收盘价5744元/...
“声动”二十四节气|小暑:汗滴... 05:23万物渐盛暑气蒸腾我们迎来夏季的第五个节气小暑小暑大暑上蒸下煮高温高湿天气增多公众需注意防暑...