Moz*_*ini 3 java maven spring-boot grpc
我是 gRpc 的新手,我尝试使用 gRpc 1.27.1 和 protobuf 3.11 在 Java 11(Spring Boot 2) 服务器和 Java 8 (Spring Boot 1.5) 客户端之间使用它。
这是我的设置:
我有数据模型库,只有 1 个 proto 定义文件和 Maven 文件来生成在客户端和服务器之间共享的 java 源代码
的相关部分pom.xml:
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<grpcVersion>1.27.1</grpcVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpcVersion}</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.11.4:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.27.1:exe:${os.detected.classifier}
</pluginArtifact>
<clearOutputDirectory>false</clearOutputDirectory>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run Code Online (Sandbox Code Playgroud)
服务器 pom.xml 的片段:
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpcVersion>1.27.1</grpcVersion>
<local.repository.folder>${pom.basedir}/lib/</local.repository.folder>
</properties>
Run Code Online (Sandbox Code Playgroud)
<dependency>
<!-- Java 9+ compatibility -->
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpcVersion}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpcVersion}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpcVersion}</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.7.0.RELEASE</version>
</dependency>
<!-- For the server (only) -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.7.0.RELEASE</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
客户端项目pom.xml的相关部分:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<local.repository.folder>${pom.basedir}/lib/</local.repository.folder>
<grpcVersion>1.27.1</grpcVersion>
</properties>
<dependencies>
<!-- This is the data model protobuf project -->
<dependency>
<groupId>e2log</groupId>
<artifactId>nsub-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- This is the service definition protobuf project -->
<dependency>
<groupId>e2log</groupId>
<artifactId>e2log-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpcVersion}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpcVersion}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpcVersion}</version>
</dependency>
<!-- There are a ton of other dependencies here that i am omitting for brevity-->
Run Code Online (Sandbox Code Playgroud)
我的服务目前只有一个非常简单的 rpc 定义:
syntax = "proto3";
import "E2logData.proto";
option java_multiple_files = true;
package e2log.nsub.bridge;
service EventBridgeService {
rpc RfqNotification( e2log.api.RfqNotificationEvent ) returns ( RfqNotificationResponse ) {}
}
message RfqNotificationResponse{
bool relay_message = 1;
e2log.api.RfqNotificationEvent request = 2;
}
Run Code Online (Sandbox Code Playgroud)
客户端实现的相关部分位于注释为 Spring 的类中@Component:
// Connection with gRpc server
@PostConstruct
void init(){
channel = nSubConnection();
log.info("Established NSub gRpc connection for address={} with max-retries={}.", nsubServer, nSubMaxRetryAttempts);
eventBridgeSvcBlockingStub = EventBridgeServiceGrpc.newBlockingStub(channel);
}
@VisibleForTesting
ManagedChannel nSubConnection() {
return ManagedChannelBuilder.forTarget(nsubServer )
.enableRetry()
.maxRetryAttempts(nSubMaxRetryAttempts)
.usePlaintext() // for now until it works
.build();
}
// Actual gRpc call
@EventListener
public void nSubBridge(RfqEvent event){
val wireEvent = rfqEventMapper.map(event);
val resp = eventBridgeSvcBlockingStub.rfqNotification( wireEvent);
//
System.err.println(resp);
}
Run Code Online (Sandbox Code Playgroud)
一切都编译并启动得很好,当客户端调用服务器时,服务器接收该调用并打印出客户端序列化为 protbuf 的有效负载中发送的收到的电子邮件地址。然而,在服务器上打印出消息后,我首先在客户端收到错误,然后在服务器端收到错误。
ndler | Not auditing event RfqAwardedEvent for RFQ 1023-2020 action=false, user=true
23:26:00.193 | ERROR | c.e.s.i.LoginServiceImpl | error in handleException :: UNIMPLEMENTED: Method e2log.nsub.bridge.EventBridgeService/RfqNotification is unimplemented
io.grpc.StatusRuntimeException: UNIMPLEMENTED: Method e2log.nsub.bridge.EventBridgeService/RfqNotification is unimplemented
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:240)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:221)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:140)
at e2log.nsub.bridge.EventBridgeServiceGrpc$EventBridgeServiceBlockingStub.rfqNotification(EventBridgeServiceGrpc.java:169)
at com.e2log.rfq.event.RfqEventHandler.nSubBridge(RfqEventHandler.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:256)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:177)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:140)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360)
at com.e2log.service.impl.PreawardToAwardTransition.notifyLspAndShipper(PreawardToAwardTransition.java:124)
at com.e2log.service.impl.PreawardToAwardTransition.preAwardedToAwarded(PreawardToAwardTransition.java:75)
at com.e2log.service.impl.CustomerServiceImpl.customerPreAwardedtoAward(CustomerServiceImpl.java:545)
at com.e2log.service.impl.CustomerServiceImpl$$FastClassBySpringCGLIB$$c32e4446.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:669)
at com.e2log.service.impl.CustomerServiceImpl$$EnhancerBySpringCGLIB$$eee40a0b.customerPreAwardedtoAward(<generated>)
at com.e2log.controller.CustomerController.customerPreAwardedtoAward(CustomerController.java:235)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:664)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:244)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.e2log.exception.BadRequestFilter.doFilterInternal(BadRequestFilter.java:43)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at com.e2log.security.AuthenticationFilter.doFilterInternal(AuthenticationFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethod
事实证明我没有发布我的服务器代码,这就是问题所在。
我将在这里发布我的错误,以便其他人不必花时间处理这个愚蠢的错误:
@Override
public void newRfqNotification(RfqNotificationEvent request, StreamObserver<RfqNotificationResponse> responseObserver) {
super.newRfqNotification(request, responseObserver);
/*
My business logic to process the incoming request omitted.
*/
}
Run Code Online (Sandbox Code Playgroud)
super.newRfqNotification()当我调用 IntelliJ[Override Methods... ^O]创建一个模板方法来填充业务逻辑时,就创建了对上面的调用。
我以某种方式开始编写我的业务逻辑,而不删除对 super 的调用,这在许多情况下很好,但在这种情况下是灾难性的。那么发生的情况是 super 方法正常处理并向客户端发送一个答案,表示该方法尚未实现,并继续调用 super() 后编写的业务逻辑。请参阅下面的实现:
生成方法(超级):
/**
*/
public void newRfqNotification(e2log.api.RfqNotificationEvent request,
io.grpc.stub.StreamObserver<e2log.nsub.bridge.RfqNotificationResponse> responseObserver) {
asyncUnimplementedUnaryCall(getNewRfqNotificationMethod(), responseObserver);
}
Run Code Online (Sandbox Code Playgroud)
其中调用:
/**
* Sets unimplemented status for method on given response stream for unary call.
*
* @param methodDescriptor of method for which error will be thrown.
* @param responseObserver on which error will be set.
*/
public static void asyncUnimplementedUnaryCall(
MethodDescriptor<?, ?> methodDescriptor, StreamObserver<?> responseObserver) {
checkNotNull(methodDescriptor, "methodDescriptor");
checkNotNull(responseObserver, "responseObserver");
responseObserver.onError(Status.UNIMPLEMENTED
.withDescription(String.format("Method %s is unimplemented",
methodDescriptor.getFullMethodName()))
.asRuntimeException());
}
Run Code Online (Sandbox Code Playgroud)
然后客户端收到Status.UNIPLEMENTED响应并关闭流,这会导致服务器错误。
| 归档时间: |
|
| 查看次数: |
22300 次 |
| 最近记录: |