成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一個簡單的案例入門 gRPC

開發(fā) 項目管理
小伙伴們看到,這里首先需要和服務(wù)端建立連接,給出服務(wù)端的地址和端口號即可,usePlaintext() 方法表示不使用 TLS 對連接進行加密(默認(rèn)情況下會使用 TLS 對連接進行加密),生產(chǎn)環(huán)境建議使用加密連接。

這篇文章本來要在年前和小伙伴們見面,但是因為我之前的 Mac 系統(tǒng)版本是 10.13.6,這個版本比較老,時至今天在運行一些新鮮玩意的時候有時候會有一些 BUG(例如運行最新版的 Nacos 等),運行 gRPC 的插件也有 BUG,代碼總是生成有問題,但是因為系統(tǒng)升級是一個大事,所以一直等到過年放假,在家才慢慢折騰將 Mac 升級到目前的 13.1 版本,之前這些問題現(xiàn)在都沒有了,gRPC 的案例現(xiàn)在也可以順利跑起來了。

所以今天就來和小伙伴們簡單聊一聊 gRPC。

1. 緣起

我為什么想寫一篇 gRPC 的文章呢?其實本來我是想和小伙伴們梳理一下在微服務(wù)中都有哪些跨進城調(diào)用的方式,在梳理的過程中想到了 gRPC,發(fā)現(xiàn)還沒寫文章和小伙伴們聊過 gRPC,因此打算先來幾篇文章和小伙伴們詳細(xì)介紹一下 gRPC,然后再梳理微服務(wù)中的跨進程方案。

2. 什么是 gRPC

了解 gRPC 之前先來看看什么是 RPC。

RPC 全稱是 Remote Procedure Call,中文一般譯作遠程過程調(diào)用。RPC 是一種進程間的通信模式,程序分布在不同的地址空間里。簡單來說,就是兩個進程之間互相調(diào)用的一種方式。

gRPC 則是一個由 Google 發(fā)起的開源的 RPC 框架,它是一個高性能遠程過程調(diào)用 (RPC) 框架,可以在任何環(huán)境中運行。gRPC 通過對負(fù)載均衡、跟蹤、健康檢查和身份驗證的可插拔支持,有效地連接數(shù)據(jù)中心內(nèi)和數(shù)據(jù)中心之間的服務(wù)。

在 gRPC 中,客戶端應(yīng)用程序可以直接調(diào)用部署在不同機器上的服務(wù)端應(yīng)用程序中的方法,就好像它是本地對象一樣,使用 gRPC 可以更容易地創(chuàng)建分布式應(yīng)用程序和服務(wù)。與許多 RPC 系統(tǒng)一樣,gRPC 基于定義服務(wù)的思想,指定基于參數(shù)和返回類型遠程調(diào)用的方法。在服務(wù)端側(cè),服務(wù)端實現(xiàn)接口,運行 gRPC 服務(wù),處理客戶端調(diào)用。在客戶端側(cè),客戶端擁有存根(Stub,在某些語言中稱為客戶端),它提供與服務(wù)端相同的方法。

圖片

gRPC 客戶端和服務(wù)端可以在各種環(huán)境中運行和相互通信 – 從 Google 內(nèi)部的服務(wù)器到你自己的桌面 – 并且可以使用 gRPC 支持的任何語言編寫。因此,你可以輕松地用 Java 創(chuàng)建 gRPC 服務(wù)端,使用 Go、Python 或 Ruby 創(chuàng)建客戶端。此外,最新的 Google API 將包含 gRPC 版本的接口,使你輕松地將 Google 功能構(gòu)建到你的應(yīng)用程序中。

gRPC 支持的語言版本:

圖片

說了這么多,還是得整兩個小案例小伙伴們可能才會清晰,所以我們也不廢話了,上案例。

3. 實踐

先來看下我們的項目結(jié)構(gòu):

├── grpc-api
│ ├── pom.xml
│ ├── src
├── grpc-client
│ ├── pom.xml
│ ├── src
├── grpc-server
│ ├── pom.xml
│ ├── src
└── pom.xml

大家看下,這里首先有一個 grpc-api,這個模塊用來放我們的公共代碼;grpc-server 是我們的服務(wù)端,grpc-client 則是我們的客戶端,這些都是普通的 maven 項目。

3.1 grpc-api

在 grpc-api 中,我們首先引入項目依賴,如下:

<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.52.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.52.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.52.1</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
</dependencies>

除了這些常規(guī)的依賴之外,還需要一個插件:

<build>
<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.21.7:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.51.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

我來說一下這個插件的作用。

默認(rèn)情況下,gRPC 使用 Protocol Buffers,這是 Google 提供的一個成熟的開源的跨平臺的序列化數(shù)據(jù)結(jié)構(gòu)的協(xié)議,我們編寫對應(yīng)的 proto 文件,通過上面這個插件可以將我們編寫的 proto 文件自動轉(zhuǎn)為對應(yīng)的 Java 類。

多說一句,使用 Protocol Buffers 并不是必須的,也可以使用 JSON 等,但是目前來說這個場景更常用的還是 Portal Buffers。

接下來我們在 main 目錄下新建 proto 文件夾,如下:

圖片

注意,這個文件夾位置是默認(rèn)的。如果我們的 proto 文件不是放在 src/main/proto 位置,那么在配置插件的時候需要指定 proto 文件的位置,咱們本篇文章主要是入門,我這里就使用默認(rèn)的位置。

在 proto 文件夾中,我們新建一個 product.proto 文件,內(nèi)容如下:

syntax = "proto3";

option java_multiple_files = true;
option java_package = "org.javaboy.grpc.demo";
option java_outer_classname = "ProductProto";

package product;

service ProductInfo {
rpc addProduct (Product) returns (ProductId);
rpc getProduct(ProductId) returns(Product);
}

message Product {
string id = 1;
string name=2;
string descriptinotallow=3;
float price=4;
}

message ProductId {
string value = 1;
}

這段配置算是一個比較核心的配置了,這里主要說明了負(fù)責(zé)進程傳輸?shù)念悺⒎椒ǖ鹊降资莻€啥樣子:

  1. syntax = "proto3";:這個是 protocol buffers 的版本。
  2. option java_multiple_files = true;:這個字段是可選的,如果設(shè)置為 true,表示每一個 message 文件都會有一個單獨的 class 文件;否則,message 全部定義在 outerclass 文件里。
  3. option java_package = "org.javaboy.grpc.demo";:這個字段是可選的,用于標(biāo)識生成的 java 文件的 package。如果沒有指定,則使用 proto 里定義的 package,如果package 也沒有指定,那就會生成在根目錄下。
  4. option java_outer_classname = "ProductProto";:這個字段是可選的,用于指定 proto 文件生成的 java 類的 outerclass 類名。什么是 outerclass?簡單來說就是用一個 class 文件來定義所有的 message 對應(yīng)的 Java 類,這個 class 就是 outerclass;如果沒有指定,默認(rèn)是 proto 文件的駝峰式;
  5. package product;:這個屬性用來定義 message 的包名。包名的含義與平臺語言無關(guān),這個 package 僅僅被用在 proto 文件中用于區(qū)分同名的 message 類型。可以理解為 message 全名的前綴,和 message 名稱合起來唯一標(biāo)識一個 message 類型。當(dāng)我們在 proto 文件中導(dǎo)入其他 proto 文件的 message,需要加上 package 前綴才行。所以包名是用來唯一標(biāo)識 message 的。
  6. service:我們定義的跨平臺方法都寫在 service 中,上面的案例中我們定義了兩個方法:addProduct 表示添加一件商品,參數(shù)是一個 Product 對象,返回值則是剛剛添加成功的商品的 ID;getProduct 則表示根據(jù) ID 查詢一個商品,參數(shù)是一個商品 ID,返回值則是查詢到的商品對象。這里的定義相當(dāng)于一個接口,將來我們要在 Java 代碼中實現(xiàn)這個接口。
  7. message:這里有點像我們在 Java 中定義類,上文中我們定義了兩個類,分別是 Product 和 ProductId 兩個類。這兩個類在 service 中被使用。

message 中定義的有點像我們 Java 中定義的類,但是不能直接使用 Java 中的數(shù)據(jù)類型,畢竟這是 Protocol buffers,這個是和語言無關(guān)的,將來可以據(jù)此生成不同語言的代碼,這里我們可以使用的類型和我們 Java 類型之間的對應(yīng)關(guān)系如下:

圖片

另外我們在 message 中定義的屬性的時候,都會給一個數(shù)字,例如 id=1,name=2 等,這個數(shù)字將來會在二進制消息中標(biāo)識我們的字段,并且一旦我們的消息類型被使用就不應(yīng)更改,這個有點像序列化的感覺。

實際上,這個 message 編譯后的字節(jié)內(nèi)容大概像下面這樣:

圖片

這里的標(biāo)簽中的內(nèi)容包含兩部分,字段索引和字段類型,字段索引其實就是我們上面定義的數(shù)字。

定義完成之后,接下來我們就需要使用插件來生成對應(yīng)的 Java 代碼了,插件我們在前面已經(jīng)引入了,現(xiàn)在只需要執(zhí)行了,如下圖:

圖片

注意,compile 和 compile-custom 兩個指令都需要執(zhí)行。其中 compile 用來編譯消息對象,compile-custom 則依賴消息對象,生成接口服務(wù)。

首先我們點擊 compile 看看生成的代碼,如下:

圖片

再看 compile-custom 生成的代碼,如下:

圖片

好了,這樣我們的準(zhǔn)備工作就算完成了。

有的小伙伴生成的代碼文件夾顏色不對勁,此時有兩種解決辦法:1.選中目標(biāo)文件夾,右鍵單擊,選擇 Mark Directory as-> Generated Sources root;2.選中工程,右鍵單擊,選擇 Maven->Reload project。推薦使用第二種方案。

3.2 grpc-server

接下來我們創(chuàng)建 grpc-server 項目,并使該項目依賴 grpc-api,然后在 grpc-server 中,提供 ProductInfo 的具體實現(xiàn):

public class ProductInfoImpl extends ProductInfoGrpc.ProductInfoImplBase {
@Override
public void addProduct(Product request, StreamObserver<ProductId> responseObserver) {
System.out.println("request.toString() = " + request.toString());
responseObserver.onNext(ProductId.newBuilder().setValue(request.getId()).build());
responseObserver.onCompleted();
}

@Override
public void getProduct(ProductId request, StreamObserver<Product> responseObserver) {
responseObserver.onNext(Product.newBuilder().setId(request.getValue()).setName("三國演義").build());
responseObserver.onCompleted();
}
}

ProductInfoGrpc.ProductInfoImplBase 是根據(jù)我們在 proto 文件中定義的 service 自動生成的,我們的 ProductInfoImpl 繼承自該類,并且提供了我們給出的方法的具體實現(xiàn)。

以 addProduct 方法為例,參數(shù) request 就是將來客戶端調(diào)用的時候傳來的 Product 對象,返回結(jié)果則通過 responseObserver 來完成。我們的方法邏輯很簡單,我就把參數(shù)傳來的 Product 對象打印出來,然后構(gòu)建一個 ProductId 對象并返回,最后調(diào)用 responseObserver.onCompleted(); 表示數(shù)據(jù)返回完畢。

剩下的 getProduct 方法邏輯就很好懂了,我這里就不再贅述了。

最后,我們再把這個 grpc-server 項目啟動起來:

public class ProductInfoServer {
Server server;

public static void main(String[] args) throws IOException, InterruptedException {
ProductInfoServer server = new ProductInfoServer();
server.start();
server.blockUntilShutdown();
}

public void start() throws IOException {
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new ProductInfoImpl())
.build()
.start();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ProductInfoServer.this.stop();
}));
}

private void stop() {
if (server != null) {
server.shutdown();
}
}

private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
}

由于我們這里是一個 JavaSE 項目,為了避免項目啟動之后就停止,我們這里調(diào)用了 server.awaitTermination(); 方法,就是讓服務(wù)啟動成功之后不要停止。

3.3 grpc-client

最后再來看看客戶端的調(diào)用。首先 grpc-client 項目也是需要依賴 grpc-api 的,然后直接進行方法調(diào)用,如下:

public class ProductClient {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
.usePlaintext()
.build();
ProductInfoGrpc.ProductInfoBlockingStub stub = ProductInfoGrpc.newBlockingStub(channel);
Product p = Product.newBuilder().setId("1")
.setPrice(399.0f)
.setName("TienChin項目")
.setDescription("SpringBoot+Vue3實戰(zhàn)視頻")
.build();
ProductId productId = stub.addProduct(p);
System.out.println("productId.getValue() = " + productId.getValue());
Product product = stub.getProduct(ProductId.newBuilder().setValue("99999").build());
System.out.println("product.toString() = " + product.toString());
}
}

小伙伴們看到,這里首先需要和服務(wù)端建立連接,給出服務(wù)端的地址和端口號即可,usePlaintext() 方法表示不使用 TLS 對連接進行加密(默認(rèn)情況下會使用 TLS 對連接進行加密),生產(chǎn)環(huán)境建議使用加密連接。

剩下的代碼就比較好懂了,創(chuàng)建 Product 對象,調(diào)用 addProduct 方法進行添加;創(chuàng)建 ProductId 對象,調(diào)用 getProduct。Product 對象和 ProductId 對象都是根據(jù)我們在 proto 中定義的 message 自動生成的。

4. 總結(jié)

好啦,一個簡單的例子,小伙伴們先對 gRPC 入個門,后面松哥會再整幾篇文章跟大家介紹這里邊的一些細(xì)節(jié)。

責(zé)任編輯:武曉燕 來源: 江南一點雨
相關(guān)推薦

2021-06-10 07:49:26

RPCgRPC模式

2015-03-24 19:48:24

2019-11-13 15:14:31

MySQL事務(wù)數(shù)據(jù)庫

2011-03-24 09:34:41

SPRING

2009-07-14 16:02:42

JDBC例子

2020-11-09 06:38:00

ninja構(gòu)建方式構(gòu)建系統(tǒng)

2018-11-22 14:09:45

iOS架構(gòu)組件開發(fā)

2009-08-19 04:14:00

線性鏈表

2010-09-16 15:57:00

PPPoA配置

2016-03-03 14:29:15

2011-09-08 13:41:53

Widget

2020-03-26 17:00:53

HashMapputJava

2010-04-19 17:21:36

Oracle寫文件

2018-09-18 10:11:21

前端vue.jsjavascript

2021-07-20 10:30:46

Golanghttp語言

2020-09-29 15:08:47

Go UI框架開發(fā)

2011-04-12 14:58:23

加密解密類

2019-11-07 14:00:36

MySQL數(shù)據(jù)庫SQL

2016-11-08 18:53:08

編譯器

2022-10-31 08:27:53

Database數(shù)據(jù)數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 成人国产精品 | 久久久www成人免费无遮挡大片 | 91精品久久久久久综合五月天 | 91黄在线观看 | 九九热最新视频 | 天天夜夜操 | 中文字幕精品一区 | 欧美电影大全 | 91香蕉嫩草 | 91超碰在线观看 | 99福利视频导航 | 久久国产综合 | 国产精品久久久久久亚洲调教 | 伊人一二三 | av网站在线播放 | 久久久久成人精品亚洲国产 | 99久久久国产精品免费消防器 | 日韩精品在线观看一区二区三区 | 岛国av一区二区 | 亚洲中国字幕 | 秋霞电影院午夜伦 | 中文字幕日韩一区 | 国产精品1区2区3区 中文字幕一区二区三区四区 | 国产一区二区电影 | 成人h视频在线观看 | 久久久国产一区二区三区 | 成人免费看片 | 丝袜久久| 国产亚洲黄色片 | 日本中文字幕在线观看 | 91精品国产综合久久婷婷香蕉 | 久久亚洲综合 | 91视频在线 | 日韩一区二区在线播放 | 国产精品国产三级国产aⅴ中文 | av高清毛片 | 三级视频国产 | 欧美99久久精品乱码影视 | 91日韩| 久色网| 少妇一区在线观看 |