Spring Boot微服務中集成gRPC實踐經驗分享

cover

Spring Boot微服務中集成gRPC實踐經驗分享

一、業務場景描述

在某電商系統中,推薦服務、庫存服務、訂單服務等微服務需要高效、雙向流式通信,REST+HTTP已無法滿足低延遲、高并發和嚴格類型安全的需求。為此,我們選擇在Spring Boot微服務中集成gRPC,提升服務間調用性能,并充分利用protobuf帶來的強類型和跨語言支持。

二、技術選型過程

常見方案對比:

  1. REST+JSON:簡單易用,但網絡開銷大、序列化性能受限;
  2. WebSocket:支持雙向通信,但消息協議需自定義,開發成本高;
  3. gRPC:基于HTTP/2、支持雙向流和流控,性能優越,自動生成服務、客戶端代碼。

最終選型:gRPC。主要理由:

  • 基于HTTP/2,多路復用和二進制壓縮;
  • protobuf自動生成Java代碼,強類型校驗;
  • 支持流式RPC,便于實時數據處理;
  • 社區成熟,Spring生態已有starter。

三、實現方案詳解

3.1 構建項目結構

spring-grpc-demo/
├── proto/
│   └── order.proto
├── service-provider/
│   ├── src/main/java/...
│   └── build.gradle
├── service-consumer/
│   ├── src/main/java/...
│   └── build.gradle
└── common/└── build.gradle

3.2 Protobuf定義(order.proto)

syntax = "proto3";
package com.example.order;option java_multiple_files = true;
option java_package = "com.example.order.proto";
option java_outer_classname = "OrderProto";service OrderService {// 下單RPCrpc CreateOrder (OrderRequest) returns (OrderReply);// 實時訂單狀態流rpc WatchOrderStatus (OrderRequest) returns (stream OrderStatus);
}message OrderRequest {int64 userId = 1;repeated int64 productIds = 2;
}message OrderReply {int64 orderId = 1;string status = 2;
}message OrderStatus {int64 orderId = 1;string status = 2;int64 timestamp = 3;
}

3.3 Service-Provider配置

build.gradle
plugins {id 'java'id 'com.google.protobuf' version '0.8.18'id 'org.springframework.boot' version '2.7.5'
}dependencies {implementation 'org.springframework.boot:spring-boot-starter'implementation 'net.devh:grpc-server-spring-boot-starter:2.13.1.RELEASE'compile project(':common')
}protobuf {protoc { artifact = "com.google.protobuf:protoc:3.19.4" }generatedFilesBaseDir = "$projectDir/src/main/java"
} 
Spring Boot啟動類
@SpringBootApplication
public class OrderServiceProviderApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceProviderApplication.class, args);}
}
OrderServiceImpl
@GRpcService
public class OrderServiceImpl extends OrderServiceGrpc.OrderServiceImplBase {@Overridepublic void createOrder(OrderRequest req, StreamObserver<OrderReply> responseObserver) {// 模擬下單邏輯long orderId = IdGenerator.nextId();OrderReply reply = OrderReply.newBuilder().setOrderId(orderId).setStatus("CREATED").build();responseObserver.onNext(reply);responseObserver.onCompleted();}@Overridepublic void watchOrderStatus(OrderRequest req, StreamObserver<OrderStatus> responseObserver) {// 模擬訂單狀態推送long orderId = 12345L;for (String status : Arrays.asList("CREATED","PROCESSING","SHIPPED","DELIVERED")) {OrderStatus os = OrderStatus.newBuilder().setOrderId(orderId).setStatus(status).setTimestamp(System.currentTimeMillis()).build();responseObserver.onNext(os);try { Thread.sleep(1000); } catch (InterruptedException ignored) {}}responseObserver.onCompleted();}
}
application.yml
server:port: 9090
grpc:server:port: 9090enable-tls: false

3.4 Service-Consumer配置

build.gradle
plugins {id 'java'id 'com.google.protobuf' version '0.8.18'id 'org.springframework.boot' version '2.7.5'
}dependencies {implementation 'org.springframework.boot:spring-boot-starter'implementation 'net.devh:grpc-client-spring-boot-starter:2.13.1.RELEASE'compile project(':common')
}protobuf {protoc { artifact = "com.google.protobuf:protoc:3.19.4" }generatedFilesBaseDir = "$projectDir/src/main/java"
}
gRPC客戶端調用示例
@Service
public class OrderClient {@GrpcClient("order-service")private OrderServiceGrpc.OrderServiceBlockingStub blockingStub;public void createAndWatch() {OrderRequest req = OrderRequest.newBuilder().setUserId(1001).addProductIds(2001).build();OrderReply reply = blockingStub.createOrder(req);System.out.println("Order Created: " + reply.getOrderId());// 訂閱狀態流blockingStub.withDeadlineAfter(10, TimeUnit.SECONDS).watchOrderStatus(req).forEachRemaining(status -> System.out.println("Status: " + status.getStatus()));}
}
application.yml
grpc:client:order-service:address: static://localhost:9090enable-tls: false

四、踩過的坑與解決方案

  1. Protobuf版本沖突:

    • 問題:不同模塊依賴的protobuf版本不一致,生成代碼不兼容。
    • 解決:統一使用com.google.protobuf:protoc:3.19.4,在根build.gradle中強制版本管理。
  2. gRPC端口沖突:

    • 問題:Spring Boot默認端口與gRPC服務端口共用導致沖突。
    • 解決:在application.yml中分別配置server.portgrpc.server.port
  3. Deadline超時異常:

    • 問題:默認無超時時間,生產環境下客戶端無限等待。
    • 解決:使用withDeadlineAfterwithDeadline設置合理超時。
  4. 流式RPC卡頓:

    • 問題:無流控或心跳時長連接容易被防火墻中斷。
    • 解決:配置HTTP/2 keepAlive(grpc.server.keepAliveTime)或底層TCP心跳。

五、總結與最佳實踐

  • 充分利用protobuf定義協議,保持向前兼容性。
  • 在生產環境中開啟TLS加密,保障通信安全。
  • 合理設置Deadline,避免資源長時間被占用。
  • 對重要RPC接口添加鏈路追蹤(Spring Cloud Sleuth或OpenTelemetry)。
  • 根據QPS和機器性能調整gRPC線程池和流控參數。
  • 在Kubernetes環境下,可結合gRPC Load Balancer(DNS、Envoy等)實現灰度發布與高可用。
  • 定期分析堆棧與日志,提前發現長尾請求和性能瓶頸。

通過上述實踐,我們將Spring Boot微服務與gRPC集成后,服務間調用延遲降低了40%,并成功支撐了千萬級日調用量,滿足了高并發低延遲場景的業務需求。希望本文對您的gRPC之旅有所幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90414.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90414.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90414.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springboot項目編寫測試類,亂碼問題解決

?MockMvc 的默認行為? MockMvc ?默認使用 ISO-8859-1 解碼響應&#xff0c;而服務端實際返回 UTF-8 編碼數據 。 Postman 無亂碼是因瀏覽器自動識別編碼&#xff0c;但 MockMvc 需顯式配置。 ?過濾器失效場景? Spring 的 CharacterEncodingFilter ?默認只對 POST 請求生效…

打破傳統,開啟 AR 智慧課堂?

在教育領域&#xff0c;AR 智慧課堂宛如一場及時雨&#xff0c;為傳統教育模式帶來了革命性的變革&#xff0c;讓學習變得更加生動有趣、高效互動。通過 AR 技術&#xff0c;抽象的知識瞬間變得鮮活起來&#xff0c;學生們可以在虛擬與現實交織的世界中&#xff0c;探索歷史的長…

熱烈祝賀 Flink 2.0 存算分離入選 VLDB 2025

VLDB 2025 論文熱烈祝賀 Apache Flink 2.0 的重磅研究成果《Disaggregated State Management in Apache Flink 2.0 》被數據庫領域頂級會議 VLDB 2025 正式接收&#xff01;這項工作由 Apache Flink 社區 聯合 阿里巴巴實時計算 Flink 團隊 以及多位學術界研究人員共同完成&…

蓄電池能量管理matlab的simulink仿真

蓄電池能量管理matlab的simulink仿真模型 AlternatorTableData.mat , 7395 Battery_Management_Lib.mdl , 577258 Readme.txt , 1293 license.txt , 1551 ssc_battery_management.mdl , 221248 ssc_lead_acid_battery_50Ah_ini.m , 1760 ssc_lead_acid_battery_80Ah_ini.m , 1…

MyBatisPlus-03-擴展功能

文章目錄【README】【1】基于MyBatisPlus的代碼生成器【2】MyBatisPlus-DB靜態工具【2.1】使用MyBatisPlus的DB靜態工具查詢單個及多個用戶地址【查詢單個用戶的訪問效果】【查詢多個用戶的訪問效果】【3】邏輯刪除【3.1】代碼實現【4】枚舉處理器【4.1】代碼實現【5】JSON處理…

初識Neo4j之Cypher(三)

目錄 一、介紹 二、語法 1、節點 2、關系 3、屬性 4、模式 一、介紹 Cypher 是 Neo4j 的聲明式查詢語言&#xff0c;兼容 GQL 標準。通過 openCypher 項目&#xff0c;Cypher 以開源方式提供。它類似于 SQL&#xff0c;但專為圖數據優化。 Cypher 直觀且接近自然語言&…

19-C#靜態方法與靜態類

C#靜態方法與靜態類 1.static-靜態方法animal.eat&#xff08;&#xff09;;//直接調用 public class animal {public static void eat()//定義靜態方法{messagebox.show("animal eat");} }2.static-靜態類animal.eat&#xff08;&#xff09;;//直接調用public stat…

基于YOLO的足球檢測Web應用:從訓練到部署的完整實戰

用Python和深度學習技術打造一個完整的足球檢測系統&#xff0c;支持圖片檢測、視頻分析和實時監控。本文帶你從零開始構建一個專業的Web應用。&#x1f3af; 項目背景 在體育賽事分析和足球訓練中&#xff0c;準確識別和定位足球是一個重要需求。本項目利用YOLO深度學習算法&a…

npm 切換 node 版本 和npm的源

在開發過程中&#xff0c;不同項目可能需要不同版本的 Node.js&#xff0c;同時 于由XX原因&#xff0c;我們需要切換npm的源。這時如果需要切換node版本或者npm的源&#xff0c;我們可以使用以下方法。 使用 nvm 切換 Node 版本 1、安裝 npm install nvm -g2、使用 # 列出所有…

Java學習第二十部分——EasyMock

目錄 一.概述 二.作用 三.工作原理 四.使用示例 五.主要特點 六.適用場景 七.其他模擬框架比較 八.idea簡單項目實戰 1.打開idea創建Java項目&#xff0c;注意構建系統選“Maven” 2.為pom.xml文件添加如下依賴&#xff0c;并重新加載Maven依賴&#xff0c;直至不報錯…

機器學習模型在C++平臺的部署

一、概述機器學習模型的訓練通常在Python環境下完成&#xff0c;而現實生產環境的復雜性和多樣性使得模型的部署成為一個值得關注的重點。不同應用場景下有不同適應的實現方式&#xff0c;這里主要介紹通過一種通用中間格式——ONNX&#xff08;Open Neural Network Exchange&a…

保姆級安裝 Ruby 環境下載及安裝教程, RubyInstaller下載及安裝教程

一、下載安裝 RubyInstaller 1.打開 RubyInstaller 官網&#xff1a;https://rubyinstaller.org/ 點擊跳轉, 官網界面如下圖&#xff1a; 點擊下載最新的 RubyDevkit 版本&#xff08;如 RubyDevkit 3.4.X (x64) &#xff09;。如下圖所示&#xff1a; 注意點&#xff1a;如果…

SQL 一鍵生成 Go Struct!支持字段注釋、類型映射、結構體命名規范

SQL 一鍵生成 Go Struct&#xff01;支持字段注釋、類型映射、結構體命名規范 在 Golang 開發中&#xff0c;尤其是操作數據庫時&#xff0c;我們經常會遇到這種場景&#xff1a; ? 拿到數據庫建表 SQL&#xff0c;卻要手動寫 Go struct? 字段幾十個、類型復雜&#xff0c;…

Web 前端框架選型:React、Vue 和 Angular 的對比與實踐

Web 前端框架選型&#xff1a;React、Vue 和 Angular 的對比與實踐 選擇前端框架就像選擇一個長期合作伙伴。錯誤的選擇可能會讓你的項目在未來幾年內背負沉重的技術債務&#xff0c;而正確的選擇則能讓開發效率飛速提升。 經過多年的項目實踐&#xff0c;我發現很多新人在框架…

C# 值拷貝、引用拷貝、淺拷貝、深拷貝

值拷貝定義&#xff1a;直接復制變量的值&#xff0c;適用于基本數據類型&#xff08;如int, float, char等&#xff09;。在 C# 中&#xff0c;值類型&#xff08;基本數據類型和結構體&#xff09;默認使用值拷貝。特點&#xff1a;創建原始值的完全獨立副本&#xff0c;修改…

深度學習圖像分類數據集—百種鳥類識別分類

該數據集為圖像分類數據集&#xff0c;適用于ResNet、VGG等卷積神經網絡&#xff0c;SENet、CBAM等注意力機制相關算法&#xff0c;Vision Transformer等Transformer相關算法。 數據集信息介紹&#xff1a;525種鳥類識別分類 訓練數據集總共有84635張圖片&#xff0c;每個文件夾…

零基礎 “入坑” Java--- 八、類和對象(一)

文章目錄一、初識面向對象二、類的定義和使用1.認識類2.類的定義格式三、類的實例化四、this引用五、對象的構造及初始化1.有關初始化2.構造方法3.就地初始化一、初識面向對象 Java是一門純面向對象的語言&#xff08;OOP&#xff09;&#xff0c;在面向對象的世界里&#xff…

數字孿生技術引領UI前端設計新篇章:智能物聯網的深度集成

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;數字孿生與物聯網的共生革命在智能設備爆發式增長的今天&#xff0c;傳統…

代碼審計-shiro漏洞分析

一、關于shiro介紹 簡單講&#xff0c;shiro是apache旗下的一個Java安全框架&#xff0c;輕量級簡單易上手&#xff0c;框架提供很多功能接口&#xff0c;常見的身份認證 、權限認證、會話管理、Remember 記住功能、加密等等。 二、漏洞分析 1.CVE-2019-12422-shiro550 漏洞原理…

EF提高性能(查詢禁用追蹤)(關閉延遲加載)

EF默認是支持延遲加載的&#xff0c;在加載一個表的數據時&#xff0c;會把關聯表的數據一并加載&#xff0c;這樣會影響性能。 一般建議關閉延遲加載可以提高EF加載的性能。還有其他方法提高性能&#xff08;查詢禁用追蹤&#xff09; 如果要實現延遲加載&#xff0c;必須滿足…