昆明免费网站建设,江宁建设局网站,上海出口贸易公司,佛山网约车驾驶员资格证网上报名#x1f680; 前言#xff1a;为什么是 gRPC#xff1f;
在微服务架构中#xff0c;RESTful API 虽然通用#xff0c;但在内部服务调用场景下#xff0c;它的效率成为了瓶颈#xff08;JSON 序列化慢、HTTP/1.1 头部冗余#xff09;。
gRPC 基于 HTTP/2 和 Protobuf 前言为什么是 gRPC在微服务架构中RESTful API 虽然通用但在内部服务调用场景下它的效率成为了瓶颈JSON 序列化慢、HTTP/1.1 头部冗余。gRPC基于HTTP/2和Protobuf提供了二进制传输、多路复用、双向流等特性性能比 REST 高出一个数量级。本文将带你从 0 构建一个包含普通调用和流式调用的订单服务并手写拦截器和单元测试。️ 第一阶段环境搭建与 IDL 定义gRPC 的核心是Contract First契约优先。我们需要先写.proto文件。1. Maven 依赖与插件这是最容易劝退新手的环节。你需要配置protobuf-maven-plugin来自动生成 Java 代码。dependenciesdependencygroupIdio.grpc/groupIdartifactIdgrpc-netty-shaded/artifactIdversion1.54.0/version/dependencydependencygroupIdio.grpc/groupIdartifactIdgrpc-protobuf/artifactIdversion1.54.0/version/dependencydependencygroupIdio.grpc/groupIdartifactIdgrpc-stub/artifactIdversion1.54.0/version/dependencydependencygroupIdorg.apache.tomcat/groupIdartifactIdannotations-api/artifactIdversion6.0.53/versionscopeprovided/scope/dependency/dependenciesbuildextensionsextensiongroupIdkr.motd.maven/groupIdartifactIdos-maven-plugin/artifactIdversion1.7.1/version/extension/extensionspluginsplugingroupIdorg.xolstice.maven.plugins/groupIdartifactIdprotobuf-maven-plugin/artifactIdversion0.6.1/versionconfigurationprotocArtifactcom.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}/protocArtifactpluginIdgrpc-java/pluginIdpluginArtifactio.grpc:protoc-gen-grpc-java:1.54.0:exe:${os.detected.classifier}/pluginArtifact/configurationexecutionsexecutiongoalsgoalcompile/goalgoalcompile-custom/goal/goals/execution/executions/plugin/plugins/build2. 定义order.proto我们在src/main/proto下创建文件。为了演示深度我们定义两个接口一个简单调用一个服务端流式调用Server Streaming。syntax proto3; package com.example.grpc; option java_multiple_files true; option java_package com.example.grpc.lib; option java_outer_classname OrderProto; service OrderService { // 1. 简单一元调用根据 ID 查订单 rpc GetOrder (OrderRequest) returns (OrderResponse); // 2. 服务端流式调用实时获取订单状态流 rpc WatchOrderStatus (OrderRequest) returns (stream OrderStatus); } message OrderRequest { int32 order_id 1; } message OrderResponse { int32 order_id 1; string product_name 2; double price 3; } message OrderStatus { string status 1; string timestamp 2; }执行mvn compile你会发现在target/generated-sources下生成了 Java 代码。 第二阶段服务端实现 (Server)服务端需要继承生成的ImplBase类。publicclassOrderServiceImplextendsOrderServiceGrpc.OrderServiceImplBase{// 1. 实现简单调用OverridepublicvoidgetOrder(OrderRequestrequest,StreamObserverOrderResponseresponseObserver){System.out.println(收到查询请求 ID: request.getOrderId());// 模拟数据库查询OrderResponseresponseOrderResponse.newBuilder().setOrderId(request.getOrderId()).setProductName(MacBook Pro M3).setPrice(12999.00).build();// 返回数据responseObserver.onNext(response);// 结束调用 (必须调用否则客户端会一直等待)responseObserver.onCompleted();}// 2. 实现服务端流式调用 (Server Streaming)OverridepublicvoidwatchOrderStatus(OrderRequestrequest,StreamObserverOrderStatusresponseObserver){// 模拟订单状态变化每隔1秒推送一次String[]statuses{已下单,支付成功,仓库配货,已发货,派送中};for(Stringstatus:statuses){try{Thread.sleep(500);}catch(InterruptedExceptione){}OrderStatusorderStatusOrderStatus.newBuilder().setStatus(status).setTimestamp(System.currentTimeMillis()).build();// 推送一条流数据responseObserver.onNext(orderStatus);}responseObserver.onCompleted();}}启动 ServerpublicclassGrpcServer{publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{// 添加拦截器 (后面讲)ServerserverServerBuilder.forPort(9090).addService(ServerInterceptors.intercept(newOrderServiceImpl(),newAuthInterceptor())).build();server.start();System.out.println(gRPC Server started on port 9090);server.awaitTermination();}} 第三阶段客户端调用 (Client)客户端通常使用Stub (存根)来调用。publicclassGrpcClient{publicstaticvoidmain(String[]args){// 1. 创建通道 (Connection)ManagedChannelchannelManagedChannelBuilder.forAddress(localhost,9090).usePlaintext()// 测试环境使用明文传输.build();// 2. 创建 Stub// BlockingStub: 同步阻塞调用OrderServiceGrpc.OrderServiceBlockingStubblockingStubOrderServiceGrpc.newBlockingStub(channel);// 3. 简单调用OrderResponseresponseblockingStub.getOrder(OrderRequest.newBuilder().setOrderId(1001).build());System.out.println(查询结果: response.getProductName());// 4. 流式调用 (需要用 Iterator)IteratorOrderStatusstatusIteratorblockingStub.watchOrderStatus(OrderRequest.newBuilder().setOrderId(1001).build());while(statusIterator.hasNext()){OrderStatusstatusstatusIterator.next();System.out.println(当前状态: status.getStatus());}channel.shutdown();}}️ 第四阶段进阶 —— 拦截器 (Interceptor)在生产环境中我们不可能裸奔。我们需要拦截器来做Auth 鉴权或日志记录。gRPC 使用Metadata(类似 HTTP Header) 来传递元数据。服务端拦截器验证 TokenpublicclassAuthInterceptorimplementsServerInterceptor{privatestaticfinalMetadata.KeyStringTOKEN_KEYMetadata.Key.of(auth-token,Metadata.ASCII_STRING_MARSHALLER);OverridepublicReqT,RespTServerCall.ListenerReqTinterceptCall(ServerCallReqT,RespTcall,Metadataheaders,ServerCallHandlerReqT,RespTnext){// 获取客户端传来的 TokenStringtokenheaders.get(TOKEN_KEY);if(secret-123.equals(token)){// 验证通过放行returnnext.startCall(call,headers);}else{// 验证失败直接关闭连接call.close(Status.UNAUTHENTICATED.withDescription(Token无效),headers);returnnewServerCall.Listener(){};}}}客户端发送 Token// 客户端需要自定义一个 CallCredentials 或者使用 ClientInterceptor// 这里使用 MetadataUtils 快速注入OrderServiceGrpc.OrderServiceBlockingStubstubOrderServiceGrpc.newBlockingStub(channel);MetadatametanewMetadata();meta.put(Metadata.Key.of(auth-token,Metadata.ASCII_STRING_MARSHALLER),secret-123);// 将 Metadata 附着在 Stub 上stubMetadataUtils.attachHeaders(stub,meta); 第五阶段单元测试 (Test)这是区分新手和高手的地方。不要启动真实的 Server 去测太慢且依赖网络。gRPC 提供了grpc-testing库支持InProcessServer (进程内服务器)速度极快。引入依赖dependencygroupIdio.grpc/groupIdartifactIdgrpc-testing/artifactIdversion1.54.0/versionscopetest/scope/dependency编写 JUnit 5 测试用例publicclassOrderServiceTest{privateServerinProcessServer;privateManagedChannelinProcessChannel;privateOrderServiceGrpc.OrderServiceBlockingStubblockingStub;BeforeEachpublicvoidsetUp()throwsException{// 生成唯一的服务器名称StringserverNameInProcessServerBuilder.generateName();// 1. 启动进程内服务器 (绑定我们实现的 Service)inProcessServerInProcessServerBuilder.forName(serverName).directExecutor()// 不使用线程池直接在当前线程执行方便测试.addService(newOrderServiceImpl()).build().start();// 2. 创建连接到该服务器的 ChannelinProcessChannelInProcessChannelBuilder.forName(serverName).directExecutor().build();blockingStubOrderServiceGrpc.newBlockingStub(inProcessChannel);}AfterEachpublicvoidtearDown(){inProcessChannel.shutdown();inProcessServer.shutdown();}TestpublicvoidtestGetOrder(){// givenOrderRequestrequestOrderRequest.newBuilder().setOrderId(888).build();// whenOrderResponseresponseblockingStub.getOrder(request);// thenassertEquals(888,response.getOrderId());assertEquals(MacBook Pro M3,response.getProductName());}} 总结通过这篇文章你掌握了 gRPC 开发的完整闭环IDL 定义proto文件是核心契约。流式通信用StreamObserver实现实时推送。拦截器用Metadata实现 Token 鉴权。InProcess 测试不依赖网络的极速单元测试。gRPC 不仅仅是高性能更是规范化微服务调用的利器。