免費(fèi)空間申請(qǐng)網(wǎng)站網(wǎng)絡(luò)營(yíng)銷在哪里學(xué)比較靠譜
在本文中,您將學(xué)習(xí)如何實(shí)現(xiàn)通過 gRPC 通信的 Spring Boot 應(yīng)用程序。gRPC 是一個(gè)現(xiàn)代開源遠(yuǎn)程過程調(diào)用 (RPC) 框架,可以在任何環(huán)境中運(yùn)行。默認(rèn)情況下,它使用 Google 的 Protocol Buffer 來序列化和反序列化結(jié)構(gòu)化數(shù)據(jù)。當(dāng)然,我們也可以切換為其他數(shù)據(jù)格式,例如JSON。為了簡(jiǎn)化我們對(duì) gRPC 和 Spring Boot 的探索,我們將為此使用專用的啟動(dòng)器gRPC Spring Boot starter。
由于 gRPC 和 Spring Boot 之間的集成沒有官方支持的啟動(dòng)器,因此我們將選擇最流行的第三方項(xiàng)目。它在GitHub上有大約 3100 顆星。您可以在此處找到有關(guān)其功能的詳細(xì)文檔。
源代碼
如果您想自己嘗試一下,可以隨時(shí)查看我的源代碼。為此,您需要克隆我的 GitHub 存儲(chǔ)庫(kù)。它包含四個(gè)應(yīng)用程序。其中兩個(gè)account-service
與customer-service
我之前的文章相關(guān),該文章介紹了 Java 中的 Protocol Buffers。當(dāng)前文章請(qǐng)參考另外兩個(gè)appaccount-service-grpc
和customer-service-grpc
。它們與相應(yīng)的應(yīng)用程序非常相似,但使用我們的第三方 Spring Boot 和 gRPC 通信而不是 REST。另外,他們需要使用 Spring Boot 2,因?yàn)槲覀兊牡谌絾?dòng)器仍然不支持 Spring Boot 3。無論如何,一旦您克隆了存儲(chǔ)庫(kù),只需按照我的說明操作即可!
為 gRPC 生成模型類和服務(wù)
第一步,我們將使用.proto
清單生成模型類和 gRPC 服務(wù)。我們需要包含一些額外的 Protobuf 模式才能使用google.protobuf.*
包**(1)。我們的 gRPC 服務(wù)將提供使用各種條件搜索帳戶的方法以及添加新帳戶的單一方法(2)。這些方法將使用文件google.protobuf.*
中定義的包和模型類中的原.proto
語(yǔ)作為消息。定義了兩條消息。該Account
消息代表單個(gè)模型類。它包含三個(gè)字段:id
、number
和customer_id
(3)。該消息包含對(duì)象Accounts
列表(4)**。Account
syntax = "proto3";
package model;
option java_package = "pl.piomin.services.grpc.account.model";
option java_outer_classname = "AccountProto";
// (1)
import "empty.proto";
import "wrappers.proto";
// (2)
service AccountsService {
rpc FindByNumber(google.protobuf.StringValue) returns (Account) {}
rpc FindByCustomer(google.protobuf.Int32Value) returns (Accounts) {}
rpc FindAll(google.protobuf.Empty) returns (Accounts) {}
rpc AddAccount(Account) returns (Account) {}
}
// (3)
message Account {
int32 id = 1;
string number = 2;
int32 customer_id = 3;
}
// (4)
message Accounts {
repeated Account account = 1;
}
您可能還記得,有兩個(gè)示例 Spring Boot 應(yīng)用程序。讓我們看一下.proto
第二個(gè)應(yīng)用程序的架構(gòu)customer-service-grpc
。它比之前的定義稍微復(fù)雜一些。我們的 gRPC 服務(wù)還將提供多種用于搜索對(duì)象的方法和一種用于添加新客戶的方法**(1)。正在customer-service-grpc
與應(yīng)用程序通信account-service-grpc
,因此我們需要生成Account
消息Accounts
( 2)。當(dāng)然,您可以使用生成的 Protobuf 類創(chuàng)建一個(gè)額外的接口模塊,并在我們的兩個(gè)示例應(yīng)用程序之間共享它。最后,我們必須定義我們的模型類。該類Customer
包含三個(gè)原始字段id
, pesel
, name
, 枚舉type
,以及分配給特定客戶的帳戶列表(3)**。還有Customers
包含對(duì)象列表Customer
(4) 的消息。
syntax = "proto3";
package model;
option java_package = "pl.piomin.services.grpc.customer.model";
option java_outer_classname = "CustomerProto";
import "empty.proto";
import "wrappers.proto";
// (1)
service CustomersService {
rpc FindByPesel(google.protobuf.StringValue) returns (Customer) {}
rpc FindById(google.protobuf.Int32Value) returns (Customer) {}
rpc FindAll(google.protobuf.Empty) returns (Customers) {}
rpc AddCustomer(Customer) returns (Customer) {}
}
// (2)
message Account {
int32 id = 1;
string number = 2;
int32 customer_id = 3;
}
message Accounts {
repeated Account account = 1;
}
// (3)
message Customer {
int32 id = 1;
string pesel = 2;
string name = 3;
CustomerType type = 4;
repeated Account accounts = 5;
enum CustomerType {
INDIVIDUAL = 0;
COMPANY = 1;
}
}
// (4)
message Customers {
repeated Customer customers = 1;
}
為了從.proto
模式生成 Java 類,我們將使用 Maven 插件。您可以使用一些可用的插件來實(shí)現(xiàn)這一點(diǎn)。我的選擇落在了protoc-jar-maven-plugin
插件上。在配置中,我們需要將 .proto 架構(gòu)的默認(rèn)位置覆蓋為src/main/proto
. 我們還需要.proto
使用includeDirectories
標(biāo)簽包含在清單中使用的其他 Protobuf 模式。這些清單位于src/main/proto-imports
目錄內(nèi)。輸出目標(biāo)目錄為src/main/generated
. 默認(rèn)情況下,該插件不生成 gRPC 服務(wù)。為了啟用它,我們需要在類型outputTarget
中包含grpc-java
。為了生成類,我們將使用該protoc-gen-grpc-java
庫(kù)。
<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>3.11.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<addProtoSources>all</addProtoSources>
<includeMavenTypes>direct</includeMavenTypes>
<outputDirectory>src/main/generated</outputDirectory>
<inputDirectories>
<include>src/main/proto</include>
</inputDirectories>
<includeDirectories>
<include>src/main/proto-imports</include>
</includeDirectories>
<outputTargets>
<outputTarget>
<type>java</type>
<outputDirectory>src/main/generated</outputDirectory>
</outputTarget>
<outputTarget>
<type>grpc-java</type>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.57.2</pluginArtifact>
<outputDirectory>src/main/generated</outputDirectory>
</outputTarget>
</outputTargets>
</configuration>
</execution>
</executions>
</plugin>
我們還將src/main/generated
使用 Maven 插件將生成的 Java 代碼附加到源目錄下build-helper-maven-plugin
。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/generated</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
一旦執(zhí)行mvn clean package
命令,Maven 將生成所需的 Java 類。account-service-grpc
這是生成 Java 類后應(yīng)用程序中的最終目錄結(jié)構(gòu)。
$ tree
.
├── pom.xml
└── src
├── main
│ ├── generated
│ │ └── pl
│ │ └── piomin
│ │ └── services
│ │ └── grpc
│ │ └── account
│ │ └── model
│ │ ├── AccountProto.java
│ │ └── AccountsServiceGrpc.java
│ ├── java
│ │ └── pl
│ │ └── piomin
│ │ └── services
│ │ └── grpc
│ │ └── account
│ │ ├── AccountApplication.java
│ │ ├── repository
│ │ │ └── AccountRepository.java
│ │ └── service
│ │ └── AccountsService.java
│ ├── proto
│ │ └── account.proto
│ ├── proto-imports
│ │ ├── empty.proto
│ │ └── wrappers.proto
│ └── resources
└── test
└── java
└── pl
└── piomin
└── services
└── grpc
└── account
└── AccountServicesTests.java
使用 gRPC Spring Boot 啟動(dòng)器
一旦我們生成了所需的 Protobuf 模型類和 gRPC 存根,我們就可以繼續(xù)實(shí)施。第一步,我們需要包含以下 Spring Boot 啟動(dòng)器:
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.14.0.RELEASE</version>
</dependency>
然后我們必須創(chuàng)建gRPC服務(wù)實(shí)現(xiàn)類。AccountsServiceImplBase
它需要根據(jù)聲明擴(kuò)展生成.proto
。@GrpcService
我們還需要用(1)注釋整個(gè)類。之后,我們將重寫通過 gRPC 公開的所有方法。我們的服務(wù)使用一個(gè)簡(jiǎn)單的內(nèi)存存儲(chǔ)庫(kù)(2)。每個(gè)方法都提供一個(gè)參數(shù)對(duì)象和io.grpc.stub.StreamObserver
用于以反應(yīng)方式返回響應(yīng)的類**(3)** (4)。
@GrpcService // (1)
public class AccountsService extends AccountsServiceGrpc.AccountsServiceImplBase {
@Autowired
AccountRepository repository; // (2)
@Override
public void findByNumber(StringValue request, StreamObserver<AccountProto.Account> responseObserver) { // (3)
AccountProto.Account a = repository.findByNumber(request.getValue());
responseObserver.onNext(a); # (4)
responseObserver.onCompleted();
}
@Override
public void findByCustomer(Int32Value request, StreamObserver<AccountProto.Accounts> responseObserver) {
List<AccountProto.Account> accounts = repository.findByCustomer(request.getValue());
AccountProto.Accounts a = AccountProto.Accounts.newBuilder().addAllAccount(accounts).build();
responseObserver.onNext(a);
responseObserver.onCompleted();
}
@Override
public void findAll(Empty request, StreamObserver<AccountProto.Accounts> responseObserver) {
List<AccountProto.Account> accounts = repository.findAll();
AccountProto.Accounts a = AccountProto.Accounts.newBuilder().addAllAccount(accounts).build();
responseObserver.onNext(a);
responseObserver.onCompleted();
}
@Override
public void addAccount(AccountProto.Account request, StreamObserver<AccountProto.Account> responseObserver) {
AccountProto.Account a = repository.add(request.getCustomerId(), request.getNumber());
responseObserver.onNext(a);
responseObserver.onCompleted();
}
}
這是AccountRepository
實(shí)現(xiàn):
public class AccountRepository {
List<AccountProto.Account> accounts;
AtomicInteger id;
public AccountRepository(List<AccountProto.Account> accounts) {
this.accounts = accounts;
this.id = new AtomicInteger();
this.id.set(accounts.size());
}
public List<AccountProto.Account> findAll() {
return accounts;
}
public List<AccountProto.Account> findByCustomer(int customerId) {
return accounts.stream().filter(it -> it.getCustomerId() == customerId).toList();
}
public AccountProto.Account findByNumber(String number) {
return accounts.stream()
.filter(it -> it.getNumber().equals(number))
.findFirst()
.orElseThrow();
}
public AccountProto.Account add(int customerId, String number) {
AccountProto.Account a = AccountProto.Account.newBuilder()
.setId(id.incrementAndGet())
.setCustomerId(customerId)
.setNumber(number)
.build();
return a;
}
}
我們?cè)趩?dòng)時(shí)添加一些測(cè)試數(shù)據(jù)。這是我們的應(yīng)用程序主類:
@SpringBootApplication
public class AccountApplication {
public static void main(String[] args) {
SpringApplication.run(AccountApplication.class, args);
}
@Bean
AccountRepository repository() {
List<AccountProto.Account> accounts = new ArrayList<>();
accounts.add(AccountProto.Account.newBuilder().setId(1).setCustomerId(1).setNumber("111111").build());
accounts.add(AccountProto.Account.newBuilder().setId(2).setCustomerId(2).setNumber("222222").build());
accounts.add(AccountProto.Account.newBuilder().setId(3).setCustomerId(3).setNumber("333333").build());
accounts.add(AccountProto.Account.newBuilder().setId(4).setCustomerId(4).setNumber("444444").build());
accounts.add(AccountProto.Account.newBuilder().setId(5).setCustomerId(1).setNumber("555555").build());
accounts.add(AccountProto.Account.newBuilder().setId(6).setCustomerId(2).setNumber("666666").build());
accounts.add(AccountProto.Account.newBuilder().setId(7).setCustomerId(2).setNumber("777777").build());
return new AccountRepository(accounts);
}
}
在啟動(dòng)應(yīng)用程序之前,我們還將包含 Spring Boot Actuator 以公開一些與 gRPC 相關(guān)的指標(biāo)。我們將在與 gRPC 服務(wù)不同的端口下公開,因此我們還需要包含 Spring Boot Web starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在application.yml
文件中我們應(yīng)該啟用metrics
端點(diǎn):
spring.application.name: account-service-grpc
management.endpoints.web.exposure.include: metrics
management.endpoint.metrics.enabled: true
默認(rèn)情況下,gRPC服務(wù)在該端口下可用9090
。我們可以使用該grpc.server.port
屬性覆蓋該數(shù)字。將端口設(shè)置為 0
使用空閑的隨機(jī)端口。讓我們開始我們的示例應(yīng)用程序:
調(diào)用gRPC服務(wù)
我們可以使用grpcurl
CLI 工具來調(diào)用示例應(yīng)用程序公開的 gRPC 服務(wù)。9090
默認(rèn)情況下,gRPC 服務(wù)器將在端口使用?模式下啟動(dòng) PLAINTEXT
。為了打印可用服務(wù)的列表,我們需要執(zhí)行以下命令:
$ grpcurl --plaintext localhost:9090 list
grpc.health.v1.Health
grpc.reflection.v1alpha.ServerReflection
model.AccountsService
然后,讓我們打印 所公開的方法列表model.AccountService
:
$ grpcurl --plaintext localhost:9090 list model.AccountsService
model.AccountsService.AddAccount
model.AccountsService.FindAll
model.AccountsService.FindByCustomer
model.AccountsService.FindByNumber
我們還可以使用describe
命令中的關(guān)鍵字打印有關(guān)每個(gè)方法的詳細(xì)信息:
$ grpcurl --plaintext localhost:9090 describe model.AccountsService.FindByNumber
model.AccountsService.FindByNumber is a method:
rpc FindByNumber ( .google.protobuf.StringValue ) returns ( .model.Account );
現(xiàn)在,讓我們調(diào)用上面可見的命令所描述的端點(diǎn)。我們的方法的名稱是model.AccountsService.FindByNumber
。我們還使用111111
值設(shè)置輸入字符串參數(shù)。
$ grpcurl --plaintext -d '"111111"' localhost:9090 model.AccountsService.FindByNumber
{
"id": 1,
"number": "111111",
"customer_id": 1
}
之后我們就可以看一下model.AccountsService.FindByNumber
gRPC方法了。它接受一個(gè)整數(shù)作為輸入?yún)?shù)并返回一個(gè)對(duì)象列表。
$ grpcurl --plaintext -d '1' localhost:9090 model.AccountsService.FindByCustomer
{
"account": [
{
"id": 1,
"number": "111111",
"customer_id": 1
},
{
"id": 5,
"number": "555555",
"customer_id": 1
}
]
}
最后我們就可以調(diào)用添加新賬戶的方法了。它以 JSON 對(duì)象作為輸入?yún)?shù)。然后它將返回一個(gè)新創(chuàng)建的Account
帶有增量id
字段的對(duì)象。
$ grpcurl --plaintext -d '{"customer_id": 6, "number": "888888"}' localhost:9090 model.AccountsService.AddAccount
{
"id": 8,
"number": "888888",
"customer_id": 6
}
gRPC Spring Boot 啟動(dòng)器向執(zhí)行器添加了三個(gè)附加指標(biāo)。
我們可以顯示每個(gè) gRPC 方法的請(qǐng)求數(shù)量。這是該方法的請(qǐng)求和響應(yīng)FindByNumber
。
我們還可以顯示每種方法的平均處理時(shí)間,如下所示。
測(cè)試 gRPC 服務(wù)
在上一節(jié)中,我們使用 CLI 工具手動(dòng)運(yùn)行應(yīng)用程序并測(cè)試 gRPC 服務(wù)grpcurl
。不過,我們也可以基于Spring Boot Test模塊來實(shí)現(xiàn)單元或集成測(cè)試。我們將為我們的應(yīng)用程序與 gRPC 客戶端創(chuàng)建集成測(cè)試。為此,我們需要在 Maven 中包含以下三個(gè)依賴項(xiàng)pom.xml
:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<version>1.51.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.14.0.RELEASE</version>
<scope>test</scope>
</dependency>
在下面可見的測(cè)試實(shí)現(xiàn)中,我們需要啟用“進(jìn)程內(nèi)”服務(wù)器**(1)并禁用外部服務(wù)器(2)**。然后我們必須配置客戶端連接到“進(jìn)程內(nèi)服務(wù)器” (3)。我們將使用 Maven 構(gòu)建期間已生成的 gRPC 客戶端。它可以作為AccountsServiceBlockingStub
類使用。我們只需使用@GrpcClient
(4)對(duì)其進(jìn)行正確注入和注釋。之后,我們可以使用客戶端存根來調(diào)用我們的 gRPC 服務(wù)(5)。
@SpringBootTest(properties = {
"grpc.server.inProcessName=test", // (1)
"grpc.server.port=-1", // (2)
"grpc.client.inProcess.address=in-process:test" // (3)
})
@DirtiesContext
public class AccountServicesTests {
@GrpcClient("inProcess") // (4)
AccountsServiceGrpc.AccountsServiceBlockingStub service;
@Test
void shouldFindAll() {
AccountProto.Accounts a = service.findAll(Empty.newBuilder().build()); // (5)
assertNotNull(a);
assertFalse(a.getAccountList().isEmpty());
}
@Test
void shouldFindByCustomer() {
AccountProto.Accounts a = service.findByCustomer(Int32Value.newBuilder().setValue(1).build());
assertNotNull(a);
assertFalse(a.getAccountList().isEmpty());
}
@Test
void shouldFindByNumber() {
AccountProto.Account a = service.findByNumber(StringValue.newBuilder().setValue("111111").build());
assertNotNull(a);
assertNotEquals(0, a.getId());
}
@Test
void shouldAddAccount() {
AccountProto.Account a = AccountProto.Account.newBuilder()
.setNumber("123456")
.setCustomerId(10)
.build();
a = service.addAccount(a);
assertNotNull(a);
assertNotEquals(0, a.getId());
}
}
以下是我們的測(cè)試結(jié)果:
gRPC 微服務(wù)之間的通信
在本節(jié)中,我們將切換到customer-service-grpc
應(yīng)用程序。與之前的應(yīng)用程序相同,我們需要使用 Maven 命令生成類和 gRPC 服務(wù)存根mvn clean package
。服務(wù)實(shí)現(xiàn)也與account-service-grpc
. 不過,這一次,我們使用客戶端來調(diào)用外部 gRPC 方法。下面是 的實(shí)現(xiàn)@GrpcService
。如您所見,我們注入AccountClient
bean,然后使用它來調(diào)用account-service-grpc
應(yīng)用程序**(1)公開的 gRPC 方法。然后我們使用客戶端 bean 查找分配給特定客戶的帳戶(2)**。
@GrpcService
public class CustomersService extends CustomersServiceGrpc.CustomersServiceImplBase {
@Autowired
CustomerRepository repository;
@Autowired
AccountClient accountClient; // (1)
@Override
public void findById(Int32Value request, StreamObserver<CustomerProto.Customer> responseObserver) {
CustomerProto.Customer c = repository.findById(request.getValue());
CustomerProto.Accounts a = accountClient.getAccountsByCustomerId(c.getId()); // (2)
List<CustomerProto.Account> l = a.getAccountList();
c = CustomerProto.Customer.newBuilder(c).addAllAccounts(l).build();
responseObserver.onNext(c);
responseObserver.onCompleted();
}
@Override
public void findByPesel(StringValue request, StreamObserver<CustomerProto.Customer> responseObserver) {
CustomerProto.Customer c = repository.findByPesel(request.getValue());
responseObserver.onNext(c);
responseObserver.onCompleted();
}
@Override
public void findAll(Empty request, StreamObserver<CustomerProto.Customers> responseObserver) {
List<CustomerProto.Customer> customerList = repository.findAll();
CustomerProto.Customers c = CustomerProto.Customers.newBuilder().addAllCustomers(customerList).build();
responseObserver.onNext(c);
responseObserver.onCompleted();
}
@Override
public void addCustomer(CustomerProto.Customer request, StreamObserver<CustomerProto.Customer> responseObserver) {
CustomerProto.Customer c = repository.add(request.getType(), request.getName(), request.getPesel());
responseObserver.onNext(c);
responseObserver.onCompleted();
}
}
現(xiàn)在,我們來看看該類的實(shí)現(xiàn)AccountClient
。我們使用生成的客戶端存根來調(diào)用外部 gRPC 方法**(1)**。請(qǐng)注意注釋內(nèi)的值。這是我們客戶的名字。
@Service
public class AccountClient {
private static final Logger LOG = LoggerFactory.getLogger(AccountClient.class);
@GrpcClient("account-service-grpc") // (1)
AccountsServiceGrpc.AccountsServiceBlockingStub stub;
public CustomerProto.Accounts getAccountsByCustomerId(int customerId) {
try {
return stub.findByCustomer(Int32Value.newBuilder().setValue(customerId).build());
} catch (final StatusRuntimeException e) {
LOG.error("Error in communication", e);
return null;
}
}
}
我們需要做的最后一件事是提供目標(biāo)服務(wù)的地址。幸運(yùn)的是,gRPC Spring Boot 支持使用 Spring Cloud 進(jìn)行服務(wù)發(fā)現(xiàn)。我們將使用 Eureka 作為發(fā)現(xiàn)服務(wù)器。因此,我們的兩個(gè)示例應(yīng)用程序都需要包含 Spring Cloud Eureka 客戶端。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
我們還需要添加包含我們使用的 Spring Cloud 版本的dependencyManagement
部分。pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
為了避免與端口沖突,account-service-grpc
我們將覆蓋默認(rèn)的 gRPC 和 HTTP(執(zhí)行器)端口。我們還需要為@GrpcClient
. 首先,我們應(yīng)該與類@GrpcClient
中注釋中設(shè)置的名稱相同AccountClient
。客戶端通過明文協(xié)議進(jìn)行通信,并根據(jù)字段中設(shè)置的名稱從發(fā)現(xiàn)服務(wù)器讀取目標(biāo)服務(wù)的地址discovery:///
。
server.port: 8081
grpc.server.port: 9091
grpc:
client:
account-service-grpc:
address: 'discovery:///account-service-grpc'
enableKeepAlive: true
keepAliveWithoutCalls: true
negotiationType: plaintext
最后,我們可以運(yùn)行發(fā)現(xiàn)服務(wù)器和兩個(gè)示例微服務(wù)。Eureka 服務(wù)器可在我們的存儲(chǔ)庫(kù)中的 discovery-server 目錄中找到。運(yùn)行后,您可以轉(zhuǎn)到http://localhost:8761地址下可用的 UI 儀表板。
然后運(yùn)行我們的兩個(gè)示例 Spring Boot gRPC 微服務(wù)。您可以使用以下 Maven 命令運(yùn)行所有應(yīng)用程序:
$ mvn spring-boot:run
最后,我們來調(diào)用customer-service-grpc
與 通信的方法account-service-grpc
。grpcurl
我們?cè)俅问褂迷摴ぞ?。正如您所看到?#xff0c;它返回對(duì)象內(nèi)的帳戶列表Customer
:
最后的想法
gRPC Spring Boot Starter 提供了一些有用的功能來簡(jiǎn)化開發(fā)人員的工作。我們可以輕松地使用 來創(chuàng)建服務(wù)@GrpcService
,使用 來創(chuàng)建客戶端@GrpcClient
,或者將 gRPC 與 Spring Boot Actuator 指標(biāo)和 Spring Cloud 發(fā)現(xiàn)集成。然而,也存在一些缺點(diǎn)。該庫(kù)的開發(fā)不是很積極。每年大概有2-3個(gè)版本發(fā)布,目前還沒有對(duì)Spring Boot 3的支持。
更多Spring Boot 3文章:https://www.jdon.com/tag-34038/