在前面的文章之中我們介紹了基於Kubernetes及Istio如何一步一步把Service Mesh微服務架構玩起來!在該文章中,我們演示了一個非常貼近實戰的案例,這里回顧下該案例的結構,如下圖所示:
該案例所演示的就是我們日常使用微服務架構開發時,服務間最普遍的通信場景。在Spring Cloud微服務體系中,服務間可以通過Fegin+Ribbon組合的方式,實現服務間負載均衡方式的Http接口調用;但在Service Mesh架構中,服務發現及負載均衡等治理邏輯已經由SideCar代理,如果還希望延續Spring Cloud場景下服務間接口調用的代碼體驗,一般可以通過改寫Feign組件,去掉其中關於服務治理的邏輯,只保留簡單的接口聲明式調用邏輯來實現。
上述案例中“micro-api->micro-order”之間的服務通信調用,就是基於該方式實現的(可參考之前的文章)。但在微服務架構中除了采用Http協議通信外,對於某些對性能有着更高要求的系統來說,采用通信效率更高的RPC協議往往是更合適的選擇!
在基於Spring Cloud框架的微服務體系中,服務之間也可以通過RPC協議通信,但由於服務治理的需要,也需要一套類似於Fegin+Ribbon組合的SDK支持。例如gRPC框架就有針對Spring Boot框架的“grpc-client-spring-boot-starter”依賴支持!該項目是一個 gRPC 的 Spring Boot 模塊,可以在 Spring Boot 中內嵌一個 gRPC Server 對外提供服務,並支持 Spring Cloud 的服務發現、注冊、鏈路跟蹤等等。
那么在Service Mesh微服務體系下,服務間基於gRPC框架的通信應該怎么實現呢?接下來,我將以案例中"micro-order->micro-pay"之間的服務調用為例,演示在Service Mesh微服務架構下實現服務間的gRPC通信調用,並將案例中Http+gRPC服務間通信的完整場景串起來!
gRPC概述
在演示Service Mesh微服務架構下的gRPC通信場景之前,我們先簡單介紹下RPC協議及gRPC框架的基本知識。
RPC(Remote Procedure Call),又稱遠程過程調用,是一種通過掩藏底層網絡通信復雜性,從而屏蔽遠程和本地調用區別的通信方式。相比於Http協議,RPC協議屬於一種自定義的TCP協議,從而在實現時避免了一些Http協議信息的臃腫問題,實現了更高效率的通信。
在主流實現RPC協議的框架中,比較著名的有Dubbo、Thrift及gRPC等。因為目前主流的容器發布平台Kubernetes,以及Service Mesh開源平台Istio都是通過gRPC協議來實現內部組件之間的交互,所以在Service Mesh微服務架構中,服務間通信采用gRPC協議,從某種角度上說會更具有原生優勢。況且在此之前,gRPC框架已經在分布式、多語言服務場景中得到了大量應用,因此可以預測在Service Mesh微服務架構場景下,基於gRPC框架的微服務通信方式會逐步成為主流。
gRPC是Google發布的基於HTTP/2.0傳輸層協議承載的高性能開源軟件框架,提供了支持多種編程語言的、對網絡設備進行配置和納管的方法。由於是開源框架,通信的雙方可以進行二次開發,所以客戶端和服務器端之間的通信會更加專注於業務層面的內容,減少了對由gRPC框架實現的底層通信的關注。
接下來的內容就具體演示在Service Mesh微服務架構下,實現微服務“micro-order->micro-pay”的gRPC通信調用!
構建gRPC服務端程序(micro-pay)
首先從gRPC服務端的角度,在微服務micro-pay項目中集成gRPC-Java,並實現一個gRPC服務端程序。具體如下:
1、構建Spring Boot基本工程(micro-pay/micro-pay-client)
使用Spring Boot框架構建基本的Maven工程,為了工程代碼的復用,這里單獨抽象一個micro-pay-client工程,並定義micro-pay微服務gRPC服務接口的protobuf文件(*/proto/paycore.proto),代碼如下:
syntax = "proto3";
package com.wudimanong.pay.client;
option java_multiple_files = true;
option java_package = "com.wudimanong.micro.pay.proto";
service PayService {
//定義支付rpc方法
rpc doPay (PayRequest) returns (PayResponse);
}
message PayRequest {
string orderId = 1;
int32 amount=2;
}
message PayResponse {
int32 status = 1;
}
如上所示,創建了一個基於protobuf協議的支付接口定義文件,其中定義了支付服務PayService及其中的doPay支付rpc方法,並定義了其請求和返回參數對象,具體的語法遵循“proto3”協議。
為了能夠正常編譯和生成protobuf文件所定義服務接口的代碼,需要在項目pom.xml文件中引入jar包依賴及Maven編譯插件配置,代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
....
<dependencies>
....
<!--gRPC通信類庫(截止目前的最新版本)-->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.36.1</version>
</dependency>
</dependencies>
<build>
<!--引入gRpc框架proto文件編譯生產插件-->
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</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.12.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.36.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
這是單獨關於gRPC接口proto文件定義的工程,定義后編譯工程,maven就會根據前面定義的paycore.proto文件生成gRPC服務端/客戶端相關代碼。
完成后,繼續構建micro-pay微服務的spring boot工程代碼,並在其pom.xml文件中引入上述gRPC協議文件定義的依賴,例如:
<!--引入支付服務gRPC ProtoBuf定義依賴-->
<dependency>
<groupId>com.wudimanong</groupId>
<artifactId>micro-pay-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在micro-pay-client工程中所引入的gRPC相關的依賴及插件配置會自動繼承至micro-pay工程!
2、編寫gRPC支付服務代碼
在micro-pay代碼工程中創建一個PayCoreProvider接口代碼,用於表示支付gRPC服務的入口(類似於Controller),其代碼如下:
package com.wudimanong.micro.pay.provider;
import com.wudimanong.micro.pay.proto.PayRequest;
import com.wudimanong.micro.pay.proto.PayResponse;
import com.wudimanong.micro.pay.proto.PayServiceGrpc;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class PayCoreProvider extends PayServiceGrpc.PayServiceImplBase {
/**
* 實現ProtoBuf中定義的服務方法
*
* @param request
* @param responseStreamObserver
*/
@Override
public void doPay(PayRequest request, StreamObserver<PayResponse> responseStreamObserver) {
//邏輯處理(簡單模擬打印日志)
log.info("處理gRPC支付處理請求,orderId->{};payAmount{}", request.getOrderId(), request.getAmount());
//構建返回對象(構建處理狀態)
PayResponse response = PayResponse.newBuilder().setStatus(2).build();
//設置數據響應
responseStreamObserver.onNext(response);
responseStreamObserver.onCompleted();
}
}
上述代碼所引入的一些依賴代碼如PayServiceGrpc等,就是前面定義paycore.proto文件所生成的樁文件代碼!由於只是簡單測試,這里僅僅打印了下日志就返回了,如果涉及復雜業務還是可以按照MVC分層架構思想進行代碼拆分!
3、編寫gRPC與Spring Boot框架集成配置代碼
在Spring Cloud微服務中集成gRPC可以通過前面提到的“grpc-client-spring-boot-starter”來實現,但目前還沒有現成的支持Service Mesh架構下的集成SDK,所以這里通過手工配置定義的方式實現集成。先創建一個配置類,代碼如下:
package com.wudimanong.micro.pay.config;
import com.wudimanong.micro.pay.provider.PayCoreProvider;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class GrpcServerConfiguration {
@Autowired
PayCoreProvider service;
/**
* 注入配置文件中的端口信息
*/
@Value("${grpc.server-port}")
private int port;
private Server server;
public void start() throws IOException {
// 構建服務端
log.info("Starting gRPC on port {}.", port);
server = ServerBuilder.forPort(port).addService(service).build().start();
log.info("gRPC server started, listening on {}.", port);
// 添加服務端關閉的邏輯
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("Shutting down gRPC server.");
GrpcServerConfiguration.this.stop();
log.info("gRPC server shut down successfully.");
}));
}
private void stop() {
if (server != null) {
// 關閉服務端
server.shutdown();
}
}
public void block() throws InterruptedException {
if (server != null) {
// 服務端啟動后直到應用關閉都處於阻塞狀態,方便接收請求
server.awaitTermination();
}
}
}
如上所示,在該配置代碼中,通過gRPC-Java依賴所提供的Server對象構建了gRPC服務端啟動、停止、阻塞的方法,並在啟動時將前面定義的服務端類通過“.addService()”方法進行了加入(可考慮封裝更優雅的方式)!
為了讓該配置類與Spring Boot集成,再定義一個集成類,代碼如下:
package com.wudimanong.micro.pay.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class GrpcCommandLineRunner implements CommandLineRunner {
@Autowired
GrpcServerConfiguration configuration;
@Override
public void run(String... args) throws Exception {
configuration.start();
configuration.block();
}
}
上述代碼會在Spring Boot應用啟動時自動加載,其中的邏輯就是啟動gRPC服務,並阻塞等待連接!
接下來在配置文件中定義服務所開啟的gRPC端口,配置如下:
spring:
application:
name: micro-pay
server:
port: 9092
#定義gRPC服務開放的端口
grpc:
server-port: 18888
該配置所定義的參數在前面的服務配置類中引用,表示gRPC服務開啟的端口,這里定義的是18888!
到這里gRPC服務端工程代碼就構建完成了,從整體上看就是Spring Boot+gRPC的集成與整合,這其中沒有引入Spring Boot定制的gRPC集成SDK,目的在於避免其中所涉及的客戶端服務治理邏輯(與前面Http調用不直接引入Open Feign一樣)。
構建gRPC客戶端程序(micro-order)
接下來我們改造micro-order微服務,使其成為調用micro-pay微服務的gRPC客戶端程序!
1、引入gRPC客戶端依賴包
引入前面定義micro-pay gRPC服務時構建的micro-pay-client protobuf工程依賴,代碼如下:
<!--引入支付服務gRPC ProtoBuf定義依賴-->
<dependency>
<groupId>com.wudimanong</groupId>
<artifactId>micro-pay-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2、業務邏輯中實現gRPC服務調用
接下來在micro-order邏輯中調用gRPC支付服務,代碼示例如下:
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
/**
* 引入gRPC客戶端配置依賴
*/
@Autowired
GrpcClientConfiguration gRpcClent;
@Override
public CreateOrderBO create(CreateOrderDTO createOrderDTO) {
log.info("現在開始處理下單請求.....");
//生成訂單號
String orderId = String.valueOf(new Random(100).nextInt(100000) + System.currentTimeMillis());
//構建支付請求(gRPC調用)
PayRequest payRequest = PayRequest.newBuilder().setOrderId(orderId).setAmount(createOrderDTO.getAmount())
.build();
//使用stub發送請求到服務端
PayResponse payResponse = gRpcClent.getStub().doPay(payRequest);
log.info("pay gRpc response->" + payResponse.toString());
return CreateOrderBO.builder().orderId(orderId).status(payResponse.getStatus()).build();
}
}
如上所示,該業務邏輯在接收micro-api通過Http調用的請求后,會在邏輯實現過程中通過gRPC協議訪問支付服務,其中涉及的接口定義代碼,由protobuf文件所定義!
3、gRPC客戶端配置
上述邏輯是通過定義“GrpcClientConfiguration”gRPC客戶端配置類來實現gRPC服務調用的,該配置類代碼如下:
@Slf4j
@Component
public class GrpcClientConfiguration {
/**
* 支付gRPC Server的地址
*/
@Value("${server-host}")
private String host;
/**
* 支付gRPC Server的端口
*/
@Value("${server-port}")
private int port;
private ManagedChannel channel;
/**
* 支付服務stub對象
*/
private PayServiceGrpc.PayServiceBlockingStub stub;
public void start() {
//開啟channel
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
//通過channel獲取到服務端的stub
stub = PayServiceGrpc.newBlockingStub(channel);
log.info("gRPC client started, server address: {}:{}", host, port);
}
public void shutdown() throws InterruptedException {
//調用shutdown方法后等待1秒關閉channel
channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
log.info("gRPC client shut down successfully.");
}
public PayServiceGrpc.PayServiceBlockingStub getStub() {
return this.stub;
}
}
如上所示配置代碼,通過依服務配置文件指定的gRPC服務端地址+端口,實現對gRPC客戶端的配置,其中主要包括啟動和停止方法,並在啟動的過程中初始化gRPC服務客戶端的樁代碼的實例(可考慮更優雅地實現)。
在該配置類中所依賴的gRPC服務端地址+端口配置,依賴於服務配置文件的定義,代碼如下:
spring:
application:
name: micro-order
server:
port: 9091
#支付微服務Grpc服務地址、端口配置
server-host: ${grpc_server_host}
server-port: ${grpc_server_port}
如果是本地測試可以直接指定grpc_server_host及端口的值,但在Service Mesh微服務架構中,直接在應用的配置文件中指定其他微服務的地址及端口可能並不是很靈活,這個配置信息將在發布Kubernetes集群時,通過Kubernetes發布文件注入!
為了讓gRPC客戶端配置與Spring Boot集成,這里也需要定義一個Spring Boot加載類,代碼如下:
@Component
@Slf4j
public class GrpcClientCommandLineRunner implements CommandLineRunner {
@Autowired
GrpcClientConfiguration configuration;
@Override
public void run(String... args) throws Exception {
//開啟gRPC客戶端
configuration.start();
//添加客戶端關閉的邏輯
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
configuration.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
}
}
該代碼將在Spring Boot應用自動時自動加載!到這里micro-order gRPC客戶端配置就完成了!
將部署服務至Service Mesh架構環境
前面基於“micro-order->micro-pay”微服務間的gRPC調用場景,分別將兩個微服務改造成了gRPC服務端/客戶端。但此時從代碼上是很難看出來它們二者之間應該怎么實現調用!而這也恰恰就印證了Service Mesh架構的優勢,服務的發現、及負載均衡調用之類的服務治理邏輯,已經完全不用微服務自己管了!
在Istio中,它們是基於Kubernetes的Service發現機制+Istio-proxy(SideCar代理)來實現的。而具體的操作就是通過微服務Kubernetes服務發布文件的定義,接下來分別定義micro-order及micro-pay的Kubernetes發布文件。
先看下作為gRPC服務端的micro-pay的發布文件(micro-pay.yaml),代碼如下:
apiVersion: v1
kind: Service
metadata:
name: micro-pay
labels:
app: micro-pay
service: micro-pay
spec:
type: ClusterIP
ports:
- name: http
#容器暴露端口
port: 19092
#目標應用端口
targetPort: 9092
#設置gRPC端口
- name: grpc
port: 18888
targetPort: 18888
selector:
app: micro-pay
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: micro-pay-v1
labels:
app: micro-pay
version: v1
spec:
replicas: 2
selector:
matchLabels:
app: micro-pay
version: v1
template:
metadata:
labels:
app: micro-pay
version: v1
spec:
containers:
- name: micro-pay
image: 10.211.55.2:8080/micro-service/micro-pay:1.0-SNAPSHOT
imagePullPolicy: Always
tty: true
ports:
- name: http
protocol: TCP
containerPort: 19092
#指定服務gRPC端口
- name: grpc
protocol: TCP
containerPort: 18888
如上所示k8s發布文件,主要是定義了Service服務訪問資源及Deployment容器編排資源,這兩種資源都是Kubernetes的資源類型,在容器編排資源和服務資源中分別定義了gRPC的訪問端口,通過這種設置,后續gRPC客戶端通過Service資源訪問服務時,就能夠進行端口映射了!
而其他配置則是基本的Kubernetes發布部署邏輯,其中涉及的鏡像,需要在發布之前,通過構建的方式對項目進行Docker鏡像打包並上傳私有鏡像倉庫(如果有疑問,可以參考本號之前的文章)。
接下來繼續看看作為gRPC客戶端的micro-order微服務的k8s發布文件(micro-order.yaml),代碼如下:
apiVersion: v1
kind: Service
metadata:
name: micro-order
labels:
app: micro-order
service: micro-order
spec:
type: ClusterIP
ports:
- name: http
#此處設置80端口的原因在於改造的Mock FeignClient代碼默認是基於80端口進行服務調用
port: 80
targetPort: 9091
selector:
app: micro-order
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: micro-order-v1
labels:
app: micro-order
version: v1
spec:
replicas: 2
selector:
matchLabels:
app: micro-order
version: v1
template:
metadata:
labels:
app: micro-order
version: v1
spec:
containers:
- name: micro-order
image: 10.211.55.2:8080/micro-service/micro-order:1.0-SNAPSHOT
imagePullPolicy: Always
tty: true
ports:
- name: http
protocol: TCP
containerPort: 19091
#環境參數設置(設置微服務返回gRPC服務端的地址+端口)
env:
- name: GRPC_SERVER_HOST
value: micro-pay
- name: GRPC_SERVER_PORT
value: "18888"
在該發布文件中,需要說明的主要就是通過容器env環境參數的設置,指定了之前gRPC客戶端服務配置中所依賴的參數變量“GRPC_SERVER_HOST及GRPC_SERVER_PORT”,其中服務地址就是micro-pay微服務在Kubernetes中Service資源定義的名稱,端口則是gRPC服務端所開啟的端口。
這樣在gRPC客戶端在Kubernetes集群中根據Service名稱發起微服務調用時,Kubernetes集群自身的服務發現邏輯就能自動將請求映射到相應的Pod資源了!這其實就是Service Mesh微服務架構服務發現的基本邏輯!
接下來將微服務進行發布,這里假設你已經部署了一套Kubernetes集群並安裝了基於Istio的Service Mesh微服務架構環境,最終的部署效果如下所示:
root@kubernetes:/opt/istio/istio-1.8.4# kubectl get pods
NAME READY STATUS RESTARTS AGE
micro-api-6455654996-9lsxr 2/2 Running 2 43m
micro-order-v1-744d469d84-rnqq8 2/2 Running 0 6m28s
micro-order-v1-744d469d84-vsn5m 2/2 Running 0 6m28s
micro-pay-v1-7fd5dd4768-txq9d 2/2 Running 0 43s
micro-pay-v1-7fd5dd4768-wqw6b 2/2 Running 0 43s
如上所示,可以看到案例所涉及的微服務都被部署了,並且對應的SideCar代理(istio-proxy)也被正常啟動了!為了演示負載均衡效果,這里micro-order及micro-pay都分別被部署了兩個副本!
微服務多副本負載均衡調用演示
如果環境都沒啥問題,此時可以通過調用Istio Gateway來訪問micro-api服務,然后micro-api服務會通過Http的方式訪問micro-order服務,之后micro-order服務通過gRPC協議調用micro-pay服務。
通過curl命令訪問Istio Gateway網關服務,效果如下:
curl -H "Content-Type:application/json" -H "Data_Type:msg" -X POST --data '{"businessId": "202012102", "amount": 100, "channel": 2}' http://10.211.55.12:30844/api/order/create
如果正常返回響應結果,則說明上述調用鏈路走通了!此時分別通過觀察服務的業務日志和istio-proxy代理日志來加以觀測!
其中micro-pay兩個實例(PodA~PodB)業務日志信息:
//支付微服務接口訪問日志(POD-A)
root@kubernetes:~# kubectl logs micro-pay-v1-7fd5dd4768-txq9d micro-pay
....
2021-04-01 14:46:15.818 INFO 1 --- [ main] c.w.m.p.config.GrpcServerConfiguration : Starting gRPC on port 18888.
2021-04-01 14:46:18.859 INFO 1 --- [ main] c.w.m.p.config.GrpcServerConfiguration : gRPC server started, listening on 18888.
2021-04-01 15:07:36.709 INFO 1 --- [ault-executor-0] c.w.micro.pay.provider.PayCoreProvider : 處理gRPC支付處理請求,orderId->1617289656289;payAmount100
//支付微服務接口訪問日志(POD-B)
root@kubernetes:~# kubectl logs micro-pay-v1-7fd5dd4768-wqw6b micro-pay
...
2021-04-01 15:34:59.673 INFO 1 --- [ main] c.w.m.p.config.GrpcServerConfiguration : Starting gRPC on port 18888.
2021-04-01 15:35:06.175 INFO 1 --- [ main] c.w.m.p.config.GrpcServerConfiguration : gRPC server started, listening on 18888.
2021-04-01 15:40:22.019 INFO 1 --- [ault-executor-0] c.w.micro.pay.provider.PayCoreProvider : 處理gRPC支付處理請求,orderId->1617291624127;payAmount100
2021-04-01 15:44:31.630 INFO 1 --- [ault-executor-2] c.w.micro.pay.provider.PayCoreProvider : 處理gRPC支付處理請求,orderId->1617291867537;payAmount100
可以看到,多次訪問接口,基於gRPC的微服務調用也實現了負載均衡調用!接下來分別看下這兩個微服務的istio-proxy(SideCar代理)的日志,具體如下:
--istio-proxy代理日志(POD-A)
root@kubernetes:~# kubectl logs micro-pay-v1-7fd5dd4768-txq9d istio-proxy
...
2021-04-01T15:34:48.009972Z info Envoy proxy is ready
[2021-04-01T15:40:26.240Z] "POST /com.wudimanong.pay.client.PayService/doPay HTTP/2" 200 - "-" 22 7 498 477 "-" "grpc-java-netty/1.36.1" "8eb318e5-ac09-922d-9ca7-603a5c14bdd5" "micro-pay:18888" "127.0.0.1:18888" inbound|18888|| 127.0.0.1:57506 10.32.0.10:18888 10.32.0.12:36844 outbound_.18888_._.micro-pay.default.svc.cluster.local default
2021-04-01T15:45:18.377555Z info xdsproxy disconnected
...
[2021-04-01T15:45:34.885Z] "POST /com.wudimanong.pay.client.PayService/doPay HTTP/2" 200 - "-" 22 7 1200 171 "-" "grpc-java-netty/1.36.1" "c08d540e-db46-9228-b381-0808ac08377e" "micro-pay:18888" "127.0.0.1:18888" inbound|18888|| 127.0.0.1:33218 10.32.0.10:18888 10.32.0.2:42646 outbound_.18888_._.micro-pay.default.svc.cluster.local default
...
2021-04-01T15:52:49.825955Z info xdsproxy connecting to upstream XDS server: istiod.istio-system.svc:15012
如上所示,可以看到istio-proxy代理日志中顯示了通過post方式轉發gRPC服務的情況,而且可以看出gRRPC是采用Http/2實現的!
后記
本文通過實戰案例,演示了在Service Mesh微服務架構下,服務間通過gRPC協議實現通信調用的場景!
歡迎大家關注我的公眾號【風平浪靜如碼】,海量Java相關文章,學習資料都會在里面更新,整理的資料也會放在里面。
覺得寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!