gRPC(gRPC遠程過程調用)是由Google開發的一個現代、開源、高性能的RPC(遠程過程調用)框架。它旨在促進分布式系統之間的高效通信,特別適用於微服務架構。以下是關於gRPC及其在微服務通信中的作用的解釋:
什麼是gRPC?
gRPC是一種協議,可以使客戶端和服務器應用程序透明通信,更容易構建分布式系統。它使用HTTP/2作為傳輸協議,Protocol Buffers(Protobuf)作為接口定義語言(IDL),並提供身份驗證、負載平衡等功能。
以下是gRPC的一些特點:
- 與語言無關。gRPC支持多種編程語言,包括Java、Python、Go、C++等。
- 高效通信。它使用Protobuf進行二進制序列化,比基於文本的格式如JSON更快更節省空間。
- 基於HTTP/2。gRPC利用HTTP/2,實現多路徑傳輸、流式傳輸、降低延遲等功能。
- 強類型。服務和消息使用Protobuf定義,確保類型安全性並減少錯誤。
- 流式支持。 gRPC支持四種類型的流式傳輸:一元、伺服器流、客戶端流和雙向流。
gRPC的運作方式
1. 定義服務和消息
使用Protobuf,您可以定義服務接口(方法)和要交換的消息結構。
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
2. 生成程式碼
Protobuf編譯器(protoc
)會根據您選擇的編程語言生成客戶端和伺服器端的程式碼。
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
3. 實現伺服器
為定義的服務實現伺服器端邏輯。
4. 建立客戶端
使用生成的客戶端程式碼調用伺服器方法。
gRPC在微服務通信中的作用
微服務架構涉及將應用程序拆分為更小、獨立的服務,這些服務通過網絡通信。由於其效率和靈活性,gRPC在此背景下發揮著至關重要的作用。
1. 高性能
- gRPC使用Protobuf的二進制序列化,比基於文本的格式如JSON或XML更快速更緊湊。
- HTTP/2通過啟用多路複用和標頭壓縮減少延遲時間並提高吞吐量。
2. 嚴格的契約定義
- Protobuf強制執行服務之間的嚴格契約,降低通信錯誤的可能性。
- 通過版本控制管理服務定義的更改,確保向後兼容性。
3. 流媒體功能
- gRPC支持雙向流式傳輸,非常適合實時通信,如聊天應用或實時數據傳輸。
- 服務端和客戶端流式傳輸可有效處理大型數據集或連續數據流。
4. 互通性
- gRPC是與語言無關的,允許不同語言編寫的微服務無縫通信。
- 這在混合微服務環境中特別有用。
5. 內建功能
- gRPC提供內建支持身份驗證、加密(通過TLS)和負載平衡等功能,減少對其他庫或工具的需求。
6. 可擴展性
- gRPC的輕量級特性和高效通信使其適用於大型規模的微服務部署。
- 它與容器編排平台(如Kubernetes)很好地集成。
gRPC在微服務中的應用案例
- 服務間通信。gRPC非常適合在性能關鍵場景下的微服務間通信。
- 實時系統。其流媒體功能使其適用於遊戲、物聯網或實時分析等實時應用程式。
- 混合語言環境。當微服務使用不同語言編寫時,gRPC確保無縫通信。
- 雲原生應用程式。gRPC與Kubernetes和服務網格(例如Istio)等雲原生技術很好地集成。
gRPC 的優點
- 效率。二進制序列化和HTTP/2使gRPC更快且更節省資源。
- 類型安全。Protobuf確保強類型,減少運行時錯誤。
- 跨語言支持。支援多種程式語言。
- 流式處理。支援進階的流式處理模式,用於即時通訊。
gRPC 的挑戰
- 複雜性。設置gRPC可能比REST更複雜,因為需要Protobuf定義和代碼生成。
- 工具支援。相較於REST,調試和測試gRPC服務可能更困難,因為諸如Postman之類的工具並非為gRPC原生設計。
- 瀏覽器支援。瀏覽器不原生支援gRPC,需要像gRPC-Web這樣的工具用於基於Web的客戶端。
為何使用 Spring Boot 搭配 gRPC?
Spring Boot 是一個用於構建Java應用程式的流行框架,將其與gRPC結合可讓開發人員創建高效、可擴展和互操作的服務。借助Spring Boot的自動配置和依賴注入,整合gRPC變得簡單明了。
構建應用程式的步驟
我們將構建一個名為Greeter
的簡單gRPC服務,允許客戶端向服務器發送名稱並收到“Hello, {name}!”的回應。以下是我們的做法:
- 使用 Protocol Buffers 定義 gRPC 服務。
- 從
.proto
檔案生成 Java 類別。 - 在 Spring Boot 中實現 gRPC 伺服器。
- 在 Spring Boot 中實現 gRPC 客戶端。
- 添加一個 REST 控制器以調用 gRPC 客戶端進行測試。
- 運行應用程式並測試通訊。
1. 定義 gRPC 服務(.proto 檔案)
第一步是使用 Protocol Buffers 定義 gRPC 服務。在 src/main/proto
目錄中創建一個名為 greeter.proto
的檔案:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.grpc";
option java_outer_classname = "GreeterProto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
此檔案定義:
- 具有
SayHello
RPC 方法的Greeter
服務。 - 包含一個
name
欄位的HelloRequest
訊息。 - 包含一個
message
欄位的HelloResponse
訊息。
2. 添加相依性
要在 Spring Boot 中使用 gRPC,請將以下相依性添加到您的 pom.xml
中:
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot Web for REST Controller -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- gRPC dependencies -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.14.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.54.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.54.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.54.0</version>
</dependency>
<!-- Protobuf Java Format -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.22.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Protobuf Compiler Plugin -->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.22.2:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.54.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
這些相依性包括:
- Spring Boot Starter 用於基本應用程式設置。
- Spring Boot Web 用於 REST 控制器支援。
- 用於伺服器和客戶端實現的 gRPC 函式庫。
- 用於序列化和反序列化的 Protobuf。
3. 生成 Java 類別
運行以下 Maven 命令從 .proto
檔案生成 Java 類別:
mvn clean compile
這將在 target/generated-sources
目錄中生成 GreeterGrpc
和相關類。
4. 實現 gRPC 伺服器
接下來,在 Spring Boot 中實現 gRPC 伺服器。創建一個名為 GreeterService
的類:
package com.example.grpc.server;
import com.example.grpc.GreeterGrpc;
import com.example.grpc.GreeterProto.HelloRequest;
import com.example.grpc.GreeterProto.HelloResponse;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class GreeterService extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver responseObserver) {
String name = request.getName();
String message = "Hello, " + name + "!";
HelloResponse response = HelloResponse.newBuilder().setMessage(message).build();
// 發送回應
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
此類擴展生成的 GreeterGrpc.GreeterImplBase
並實現 sayHello
方法以處理傳入請求。
5. 實現 gRPC 客戶端
現在,在 Spring Boot 中實現 gRPC 客戶端。創建一個名為 GreeterClient
的類:
package com.example.grpc.client;
import com.example.grpc.GreeterGrpc;
import com.example.grpc.GreeterProto.HelloRequest;
import com.example.grpc.GreeterProto.HelloResponse;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.springframework.stereotype.Service;
@Service
public class GreeterClient {
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public GreeterClient() {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090)
.usePlaintext()
.build();
this.blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public String sayHello(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloResponse response = blockingStub.sayHello(request);
return response.getMessage();
}
}
此客戶端連接到 gRPC 伺服器並向 SayHello
方法發送請求。
6. 添加用於測試的 REST 控制器
為了更容易測試 gRPC 客戶端,我們將添加一個 REST 控制器來公開一個端點以調用 GreeterClient
。創建一個名為 GreeterController
的類:
package com.example.grpc.controller;
import com.example.grpc.client.GreeterClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreeterController {
private final GreeterClient greeterClient;
@Autowired
public GreeterController(GreeterClient greeterClient) {
this.greeterClient = greeterClient;
}
@GetMapping("/greet")
public String greet(@RequestParam String name) {
return greeterClient.sayHello(name);
}
}
此控制器公開一個 /greet
端點,接受一個 name
參數並返回來自 gRPC 伺服器的回應。
7. 創建 Spring Boot 應用程式
最後,創建一個 Spring Boot 應用程式來運行伺服器和客戶端:
package com.example.grpc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GrpcApplication {
public static void main(String[] args) {
SpringApplication.run(GrpcApplication.class, args);
}
}
8. 配置伺服器端口
將以下配置添加到 application.properties
中:
# gRPC 伺服器端口
grpc.server.port=9090
# Spring Boot 伺服器端口
server.port=8080
9. 運行應用程式
- 啟動 Spring Boot 應用程式。
- gRPC 伺服器將在端口
9090
上啟動。 - REST 控制器將在端口
8080
上提供。
您可以通過向 /greet
端點發送 GET 請求來測試應用程序:
curl http://localhost:8080/greet?name=World
響應將是:
"Hello, World!"
為 Spring Boot 選擇正確的 gRPC 库
在構建需要 gRPC 整合的 Spring Boot 應用程序時,開發人員通常需要在幾個庫之間進行選擇。最常討論的選項是 net.devh.grpc
、org.lognet.grpc
和 org.springframework.grpc
。
這些庫各自具有自己的優勢、劣勢和使用案例。讓我們探索這些庫之間的區別、它們的功能以及您應該為您的項目使用哪一個。
1. net.devh.grpc(grpc-spring-boot-starter)
net.devh.grpc
,也被稱為 grpc-spring-boot-starter
,是一個廣泛使用的庫,用於將 gRPC 與 Spring Boot 集成。它受到積極維護,並為在 Spring Boot 應用程序中構建 gRPC 伺服器和客戶端提供了一套強大的功能。
主要功能
- 自動配置。簡化了 gRPC 伺服器和客戶端的設置。
- Spring 整合。支持依賴注入和其他 Spring 功能。
- Spring 安全。輕鬆與 Spring Security 集成以進行安全通信。
- 健康檢查。通過 Spring Boot Actuator 提供健康檢查。
- 同步和異步通信。支持這兩種通信方式。
為什麼使用它?
- 積極維護。該庫正在積極維護和更新。
- 全面文檔。有大型社區支持的詳細文檔。
- 適用於生產環境。在生產環境中被廣泛使用。
什麼時候使用它?
- 如果您正在構建一個新的Spring Boot應用程序,並且需要可靠的、功能豐富的gRPC集成。
- 如果您想要與Spring Boot的功能(如依賴注入、安全性和健康檢查)無縫集成。
2. org.lognet.grpc(grpc-spring-boot-starter)
org.lognet.grpc
是另一個用於將gRPC與Spring Boot集成的庫。然而,與后者相比,它的維護活動較少,並且缺少一些高級功能。
主要功能
- 基本gRPC設置。為gRPC服務器和客戶端提供基本支持。
- Spring Boot集成。與Spring Boot合作,但功能較少。
為什麼使用它?
- 歷史使用。它是早期用於gRPC和Spring Boot集成的庫之一。
- 簡單易用。適用於簡單的用例。
什麼時候使用它?
- 如果您正在為已經使用此庫的舊項目工作。
- 由於維護有限且功能較少,不建議用於新項目。
3. org.springframework.grpc(Spring gRPC)
org.springframework.grpc
是一個實驗性或由社區驅動的努力,旨在將 gRPC 整合到 Spring 中。這不是官方的 Spring 項目,可能不像 net.devh.grpc
那樣成熟或功能豐富。
主要功能
- 基本的 gRPC 整合。為 gRPC 服務器和客戶端提供基本支持。
- 與 Spring 生態系統的對齊。設計與 Spring 生態系統密切對齊。
為什麼使用它?
- 實驗性用途。適合進行實驗或為該項目做出貢獻。
- Spring 對齊。如果您更喜歡使用與 Spring 緊密對齊的東西。
何時使用它?
- 僅當您在探索或為該項目做出貢獻時。
- 由於其實驗性質,不建議用於生產環境。
應該使用哪個?
對於新項目
使用 net.devh.grpc
(grpc-spring-boot-starter)。這是與 Spring Boot 整合 gRPC 的最成熟、積極維護和功能豐富的選項。其與 Spring Boot 功能的無縫整合使其成為新項目的最佳選擇。
對於現有項目
如果您已經在使用org.lognet.grpc
,請考慮遷移到net.devh.grpc
以獲得更好的支持和功能。雖然org.lognet.grpc
可能適用於舊項目,但缺乏net.devh.grpc
的積極維護和高級功能。
用於實驗用途
如果您正在探索或參與Spring gRPC集成,可以考慮使用org.springframework.grpc
。但由於其實驗性質,不建議用於生產環境。
關鍵考慮因素
- 社區支持。
net.devh.grpc
擁有更大的社區和更好的文檔,使之更容易尋找幫助和資源。 - 生產就緒性。
net.devh.grpc
在生產環境中被廣泛使用,被認為是穩定可靠的。 - 使用便捷性。
net.devh.grpc
提供自動配置和與Spring Boot的無縫集成,降低了設置的複雜性。
結論
gRPC是一個強大的微服務通信工具,提供高性能、強類型和諸如流式處理等高級功能。儘管與REST相比,它需要更多的初始設置,但其效率和可擴展性使其成為現代分佈式系統的優秀選擇。
隨著微服務架構變得越來越複雜,gRPC 在促進服務之間無縫通信方面扮演著越來越重要的角色。在本文中,我們使用 Spring Boot 3 構建了一個簡單的 gRPC 客戶端和服務器應用程序,使用 Protocol Buffers 定義了一個 gRPC 服務,生成了 Java 類,實現了服務器和客戶端,並添加了一個 REST 控制器,以便進行輕鬆測試。這個示例展示了使用 gRPC 構建高性能、可擴展和互操作的服務的功能和簡單性。您可以通過更複雜的服務、流式傳輸或錯誤處理進一步擴展它。祝您編碼愉快!
GitHub 存儲庫: grpc-client-and-server-with-spring-boot。
Source:
https://dzone.com/articles/understanding-grpc-and-its-role-in-microservices-c