1. 程式人生 > >微服務通訊方式——gRPC

微服務通訊方式——gRPC

 

微服務設計的原則是單一職責、輕量級通訊、服務粒度適當,而說到服務通訊,我們熟知的有MQ通訊,還有REST、Dubbo和Thrift等,這次我來說說gRPC,

谷歌開發的一種資料交換格式,說不定哪天就需要上了呢,多學習總是件好事。

準備:

Idea2019.03/Gradle6.0.1/Maven3.6.3/JDK11.0.4/Proto3.0/gRPC1.29.0

難度: 新手--戰士--老兵--大師

目標:

  1. 實現四種模式下的gRPC通訊

說明:

為了遇見各種問題,同時保持時效性,我儘量使用最新的軟體版本。原始碼地址,其中的day28:https://github.com/xiexiaobiao/dubbo-project

1 介紹

先引用一小段官方介紹:

Protocol Buffers - Google's data interchange format. Protocol Buffers (a.k.a., protobuf) are Google's language-neutral, platform-neutral, extensible

mechanism for serializing structured data.

Protocol Buffers,即protobuf,類比如JSON,XML等資料格式,實現了對結構化資料序列化時跨語言,跨平臺,可擴充套件的機制。通過預定義.proto檔案,

來協商通訊雙方的資料交換格式、介面方法,這即是“Protocol”的原譯。.proto

檔案能編譯為多種語言對應的程式碼,從而實現跨平臺。

grpc使用http2.0作為通訊方式,先說http2.0,它是對1.0的增強,而不是替代,特點:

  • 二進位制傳輸:相比1.0版的文字,2.0使用二進位制幀傳輸資料;
  • 多路複用:一個TCP連線中包含多個幀組成的流,再解析為不同的請求,從而可同時傳送多個請求,避免1.0版的隊頭阻塞;
  • 首部壓縮:1.0版的Header部分資訊很多,2.0使用HPACK壓縮格式減少資料量;
  • 服務端推送:服務端預先主動推送客戶端必要的資訊,從而減少延遲;

適用場景:定製化介面及資料交換格式,追求高效能,通訊對寬頻敏感

缺點:大多數HTTP Server尚不支援http2.0,Nginx目前只能將其降級為1.0處理;沒有連線池、服務發現和負載均衡的實現;

2 實戰步驟

A 普通模式

2.1 建立gradle型別專案,命名為GPRC-project,我上傳的Git程式碼中還包含了maven型別的專案,按照官方說明製作,執行方法略異,見其中.txt檔案說明。

2.2 編寫.proto檔案,GPRC-project\src\main\proto\helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.biao.grpc.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
} 

以上程式碼解析,幾個java相關引數:

  1. java_multiple_files 是否單獨生成在.proto檔案中定義的頂級message、enum、和service,否則只生成一個包裝了內部類的外部類; java_package 編譯生成的java類檔案的包位置;java_outer_classname 外部類名稱;java_generic_services是否生成各語言版本的基類(已過時);

  2. service Greeter {...} 定義服務和包含的方法;

  3. message 定義訊息體結構,這裡定義了一個 String型別,且只有一個字串型別的value成員,該成員編號為1來代替名字,這也是protobuf體積小的原因之一,別的資料描述語言(json、xml)都是通過成員名字標識,而Portobuf通過唯一編號,只是不便於查閱。

 

2.3 編寫GPRC-project\build.gradle,包含依賴引入和gradle編譯配置:

buildscript {
    repositories {
        mavenCentral()
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
    dependencies {
        // protobuf 編譯外掛,會在右側gradle--other中,新增Proto相關的任務(共6個)
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12'
    }
}

//plugins {
//    id 'java'
//    id 'com.google.protobuf'
//    id 'com.google.protobuf' version '0.8.8'
//}

apply plugin: 'java'
apply plugin: 'com.google.protobuf'


group 'com.biao.grpc'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
    maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}

dependencies {

    //這裡必須引入lib目錄的j2ee相關jar,否則即使每次手動加入jar依賴,但啟動應用時gradle會reimport,
    // 導致一直提示因少依賴而無法解析,這也是gradle引入第三方jar的方式
    compile fileTree(dir: "lib", include: "*.jar")

    testCompile group: 'junit', name: 'junit', version: '4.12'
    implementation 'io.grpc:grpc-netty-shaded:1.29.0'
    implementation 'io.grpc:grpc-protobuf:1.29.0'
    implementation 'io.grpc:grpc-stub:1.29.0'
}

sourceSets {
    main {
        proto {
            // .proto檔案目錄
            srcDir 'src/main/proto'
        }
        java {
            // include self written and generated code, 原始碼生成到一個單獨的目錄
            srcDirs 'src/main/java','generated-sources/main/java'
        }
    }
    // remove the test configuration - at least in your example you don't have a special test proto file
/*    test {
        proto {
            srcDir 'src/test/proto'
        }
        proto {
            srcDir 'src/test/java'
        }
    }*/
}

protobuf {
    // Configure the protoc executable
    protoc {
        // Download from repositories ,從倉庫下載,
        artifact = "com.google.protobuf:protoc:3.11.0"
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0'
        }
    }
    //'src' 改為'generated-sources',則會變更.proto檔案對應的java類檔案生成目錄
    generateProtoTasks.generatedFilesBaseDir = 'src/main/java'

    generateProtoTasks {
        // all() returns the collection of all protoc tasks
        all()*.plugins {
            grpc {}
        }

        // In addition to all(),you may get the task collection by various
        // criteria:

        // (Java only) returns tasks for a sourceSet
        ofSourceSet('main')
    }
}

以上程式碼解析:

  1. Moduleapply plugin: 'com.google.protobuf' 引入protobuf-gradle-plugin,作為protobuf 編譯外掛,會在右側gradle--other中,自動新增proto相關的任務(共6個)
  2. compile fileTree(dir: "lib", include: "*.jar") 這裡必須引入lib目錄的j2ee相關jar,否則即使每次手動加入jar依賴,但啟動應用時gradle會reimport,導致一直提示因少依賴而無法解析,這也是gradle引入第三方jar的正確方式
  3. implementation 'io.grpc:grpc-protobuf:1.29.0',gradle新版語法,implementation 僅僅對當前的Module提供介面,對外隱藏不必要的介面,而compile(新版升級為 api )依賴的庫將會完全參與編譯和打包,
  4. protobuf {...}中則宣告protoc-gen-grpc-java外掛來源的.proto檔案源目錄及生成目標目錄,

 

2.4 執行右側 task :gradle --> other --> generateProto,則自動生成類檔案和介面檔案(XXXGrpc),並且很貼心的是,如果原.proto檔案有註釋,

生成的檔案中會自動帶上原註釋內容。可以看到,helloworld.proto 和 stream.proto 生成的對應的檔案,前者為 6 個,後者為 1 個,因java_multiple_files引數不同。

生成檔案後,將檔案移動到src/main/java對應的包下面,並將build.gradle與自動生成檔案的部分註釋掉,否則啟動應用時,又會自動生成,導致IDE提示類重複。

 

2.5 看下原始碼,包com.biao.grpc.helloworld下面生成了對應於helloworld.proto的類和介面,包括服務、請求訊息結構體和響應訊息結構體。

com.biao.grpc.helloworld.GreeterGrpcgetSayHelloMethod 方法即約定了RPC的方法、請求/響應資料型別,並獲取方法全名:

@io.grpc.stub.annotations.RpcMethod(
      fullMethodName = SERVICE_NAME + '/' + "SayHello",
      requestType = com.biao.grpc.helloworld.HelloRequest.class,
      responseType = com.biao.grpc.helloworld.HelloReply.class,
      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
  public static io.grpc.MethodDescriptor<com.biao.grpc.helloworld.HelloRequest,
      com.biao.grpc.helloworld.HelloReply> getSayHelloMethod() {
    io.grpc.MethodDescriptor<com.biao.grpc.helloworld.HelloRequest, com.biao.grpc.helloworld.HelloReply> getSayHelloMethod;
    if ((getSayHelloMethod = GreeterGrpc.getSayHelloMethod) == null) {
      synchronized (GreeterGrpc.class) {
        if ((getSayHelloMethod = GreeterGrpc.getSayHelloMethod) == null) {
          GreeterGrpc.getSayHelloMethod = getSayHelloMethod =
              io.grpc.MethodDescriptor.<com.biao.grpc.helloworld.HelloRequest, com.biao.grpc.helloworld.HelloReply>newBuilder()
              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SayHello"))
              .setSampledToLocalTracing(true)
              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                  com.biao.grpc.helloworld.HelloRequest.getDefaultInstance()))
              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                  com.biao.grpc.helloworld.HelloReply.getDefaultInstance()))
              .setSchemaDescriptor(new GreeterMethodDescriptorSupplier("SayHello"))
              .build();
        }
      }
    }
    return getSayHelloMethod;
  }
 

2.6 建立server端:

public class HelloWorld_Server {
    private static final Logger logger = Logger.getLogger(HelloWorld_Server.class.getName());


    private int port = 50051;
    private Server server;

    private void start() throws IOException{
        server = ServerBuilder.forPort(port)
                .addService(new GreeterImpl())
                .build()
                .start();
        logger.info("Server started, listening on "+ port);

        Runtime.getRuntime().addShutdownHook(new Thread(){

            @Override
            public void run(){

                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                HelloWorld_Server.this.stop();
                System.err.println("*** server shut down");
            }
        });
    }

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

    // block 一直到退出程式
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null){
            server.awaitTermination();
        }
    }


    public  static  void main(String[] args) throws IOException, InterruptedException {

        final HelloWorld_Server server = new HelloWorld_Server();
        server.start();
        server.blockUntilShutdown();
    }


    // 實現 定義一個實現服務介面的類
    private class GreeterImpl extends com.biao.grpc.helloworld.GreeterGrpc.GreeterImplBase {

        @Override
        public void sayHello(com.biao.grpc.helloworld.HelloRequest req, 
                             StreamObserver<com.biao.grpc.helloworld.HelloReply> responseObserver){
            com.biao.grpc.helloworld.HelloReply reply = com.biao.grpc.helloworld.HelloReply.
                    newBuilder()
                    .setMessage(("Hello "+req.getName()))
                    .build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();
            System.out.println("Message from gRPC-Client:" + req.getName());
        }
    }
}

以上程式碼解析:通過GreeterImpl擴充套件GreeterGrpc.GreeterImplBase具體實現了gRPC服務的方法,作為服務端響應請求的業務邏輯。

 

2.7 建立client端:

public class HelloWorld_Client {
    private final ManagedChannel channel;
    private final com.biao.grpc.helloworld.GreeterGrpc.GreeterBlockingStub blockingStub;
    private static final Logger logger = Logger.getLogger(HelloWorld_Client.class.getName());

    public HelloWorld_Client(String host,int port){
        channel = ManagedChannelBuilder.forAddress(host,port)
                .usePlaintext()
                .build();

        blockingStub = com.biao.grpc.helloworld.GreeterGrpc.newBlockingStub(channel);
    }


    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    public  void greet(String name){
        com.biao.grpc.helloworld.HelloRequest request = com.biao.grpc.helloworld.HelloRequest
                .newBuilder()
                .setName(name)
                .build();
        com.biao.grpc.helloworld.HelloReply response;
        try{
            response = blockingStub.sayHello(request);
        } catch (StatusRuntimeException e)
        {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }
        logger.info("Message from gRPC-Server: "+response.getMessage());
    }

    public static void main(String[] args) throws InterruptedException {
        HelloWorld_Client client = new HelloWorld_Client("127.0.0.1",50051);
        try{
            String user = "world";
            if (args.length > 0){
                user = args[0];
            }
            client.greet(user);
        }finally {
            client.shutdown();
        }
    }
}

以上程式碼解析:在greet方法中,引用HelloRequest和HelloReply,併發起gRPC業務請求。

 

2.8 先執行com.biao.grpc.helloworld.HelloWorld_Server,再執行com.biao.grpc.helloworld.HelloWorld_Client, 輸出以下為成功:

B 流模式

gRPC有四種通訊模式:

  • 普通模式:一次請求對應一次響應,和普通方法請求一樣;
  • 客戶端流模式:客戶端使用流模式傳入多個請求物件,服務端返回一個響應結果;
  • 服務端流模式:一個請求物件,服務端使用流模式傳回多個結果物件;
  • 雙向流模式:客戶端流式和服務端流式組合;

前面有說過,gRPC使用http/2通訊,資料傳輸使用二進位制幀,幀是HTTP2.0通訊的最小單位,而訊息由一或多個幀組成,流是比訊息更大的通訊單位,

是TCP連線中的一個虛擬通道。每個資料流以訊息的形式傳送,訊息中的幀可以亂序傳送,然後再根據每個幀首部的流識別符號重新組裝為流。

前面的helloworld算第1種,我這裡寫了後 3 種模式,根據stream.proto開發,使用同一個server端:com.biao.grpc.stream.StreamServer,其中實現

了客戶端流模式、服務端流模式和雙向流模式3種通訊模式的具體方法實現,

public class StreamServer {

    private static int port = 8883;
    private static io.grpc.Server server;

    public void run() {
        ServiceImpl serviceImpl = new ServiceImpl();
        server = io.grpc.ServerBuilder.forPort(port).addService(serviceImpl).build();
        try {
            server.start();
            System.out.println("Server start success on port:" + port);
            server.awaitTermination();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 實現 定義一個實現服務介面的類
    private static class ServiceImpl extends StreamServiceGrpc.StreamServiceImplBase {

        @Override
        public void serverSideStreamFun(Stream.RequestData request, StreamObserver<Stream.ResponseData> responseObserver) {
            // TODO Auto-generated method stub
            System.out.println("請求引數:" + request.getText());
            for (int i = 0; i < 10; i++) {
                responseObserver.onNext(Stream.ResponseData.newBuilder()
                        .setText("你好" + i)
                        .build());
            }
            responseObserver.onCompleted();
        }

        @Override
        public StreamObserver<Stream.RequestData> clientSideStreamFun(StreamObserver<Stream.ResponseData> responseObserver) {
            // TODO Auto-generated method stub
            return new StreamObserver<Stream.RequestData>() {
                private Stream.ResponseData.Builder builder = Stream.ResponseData.newBuilder();

                @Override
                public void onNext(Stream.RequestData value) {
                    // TODO Auto-generated method stub
                    System.out.println("請求引數:" + value.getText());

                }

                @Override
                public void onError(Throwable t) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onCompleted() {
                    // TODO Auto-generated method stub
                    builder.setText("資料接收完成");
                    responseObserver.onNext(builder.build());
                    responseObserver.onCompleted();
                }
            };
        }

        @Override
        public StreamObserver<Stream.RequestData> twoWayStreamFun(StreamObserver<Stream.ResponseData> responseObserver) {
            // TODO Auto-generated method stub
            return new StreamObserver<Stream.RequestData>() {

                @Override
                public void onNext(Stream.RequestData value) {
                    // TODO Auto-generated method stub
                    System.out.println("請求引數:" + value.getText());
                    responseObserver.onNext(Stream.ResponseData.newBuilder()
                            .setText(value.getText() + ",歡迎你的加入")
                            .build());
                }

                @Override
                public void onError(Throwable t) {
                    // TODO Auto-generated method stub
                    t.printStackTrace();
                }

                @Override
                public void onCompleted() {
                    // TODO Auto-generated method stub
                    responseObserver.onCompleted();
                }
            };
        }
    }

    public static void main(String[] args) {
        StreamServer server = new StreamServer();
        server.run();
    }

}
 

另外我寫了3個client端,程式碼分析,略!執行後即可看到效果,我這裡給個雙向流的結果例子:

附:手動編譯

為了加強動手能力,我這裡也做個手動編譯生成java程式碼的步驟:

Java程式碼生成編譯器下載: https://repo.maven.apache.org/maven2/io/grpc/protoc-gen-grpc-java/

下載安裝protobuf,https://github.com/protocolbuffers/protobuf/releases?after=v3.0.0-alpha-4

To install protobuf, you need to install the protocol compiler (used to compile .proto files) and the protobuf runtime for your chosen programming language.

要使用protobuf,需先安裝協議編譯器(protocol compiler),用於編譯.proto檔案,並且作為protobuf的執行時環境。其實安裝protobuf等價於安裝其編譯環境protoc。

 

環境變數設定,將protoc的解壓目錄新增到Path下:

 

CMD下使用protoc --version命令輸出如下即為成功:

手動編譯:進入 .proto 檔案所在目錄, 使用protoc.exe生成訊息結構體,下圖中標號 2 :

protoc <待編譯檔案> --java_out=<輸出檔案儲存路徑>

使用protoc-gen-grpc-java生成服務介面:下圖中標號 3 :

protoc *.proto --plugin=protoc-gen-grpc-java=C:\protobuf-3.0-beta\protoc-gen-grpc-java-1.9.1-windows-x86_64.exe --grpc-java_out=./

 

全文完!


我的其他文章:

  • 1 分散式任務排程系統
  • 2 Dubbo學習系列之十八(Skywalking服務跟蹤)
  • 3 Spring優雅整合Redis快取
  • 4 SOFARPC模式下的Consul註冊中心
  • 5 八種控制執行緒順序的方法

       只寫原創,敬請關注 

相關推薦

服務通訊方式——gRPC

  微服務設計的原則是單一職責、輕量級通訊、服務粒度適當,而說到服務通訊,我們熟知的有MQ通訊,還有REST、Dubbo和Thrift等,這次我來說說gRPC, 谷歌開發的一種資料交換格式,說不定哪天就需要上了呢,多學習總是件好事。 準備: Idea2019.03/Gradle6.0.1/Maven

八:對服務通訊方式RPC vs REST的理解

微服務專欄地址 目錄 1. 簡介 微服務的服務都是獨立程序,服務之間的通訊的效率、穩定性等等關乎著系統是否能高效、穩定執行。常見的通訊方式有RPC及REST,從以下幾個方面去理解微服務的服務通訊方式以及選擇: 關於RPC 1.1 什麼是

SAP雲平臺以服務方式提供了Document的CRUD(增刪改查)操作。該服務基於標準的CMI

SAP. SCP SAP雲平臺 DocumentService 微服務 SAP雲平臺以微服務的方式提供了Document的CRUD(增刪改查)操作。該微服務基於標準的CMIS協議(Content Management Interoperability Service)。 同標準的CMI

Ceilometer 21、openstack元件之間通訊以及元件內服務通訊方式分析

1 openstack元件之間通訊以及元件內各服務通訊方式 1.1 openstack各元件之間的通訊方式 據我所瞭解的幾個元件,各個元件之間大部分是通過呼叫其他元件的rest api方式進行通訊, 而rest api的框架大部分是通過: wsgi + pecan 的形式搭建起來的,本質

SpringCloud服務呼叫方式之Ribbon和Feign方式

微服務呼叫方式之Ribbon的用法 匯入Ribbon的依賴 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId&

服務通訊的設計模式

https://mp.weixin.qq.com/s/zH1AbVmeB40MiiGXxQRnNQ 在我的上一篇部落格中,我談到了微服務的設計模式。現在我想更深入地探討微服務架構中最重要的模式:微服務之間的相互通訊。我仍然記得我們過去開發單一應用時通訊是一項艱鉅的任務。在那時我們必須小心的設計資

go服務系列(四) - gRPC入門

- [1. 前言](#head1) - [2. gRPC與Protobuf簡介](#head2) - [3. 安裝](#head3) - [4. 中間檔案演示](#head4) - [4.1 編寫中間檔案](#head5) - [4.2 執行protoc命令編譯成go中間檔案](#head6) - [5.

服務通訊之feign的註冊、發現過程

## 前言 feign 是目前微服務間通訊的主流方式,是springCloud中一個非常重要的元件。他涉及到了負載均衡、限流等元件。真正意義上掌握了feign可以說就掌握了微服務。 ## 一、feign的使用 feign 的使用和dubbo的使用本質上非常相似。dubbo的理念是:像呼叫本地方法一樣呼叫遠

服務通訊之feign整合負載均衡

## 前言 書接上文,feign介面是如何註冊到容器想必已然清楚,現在我們著重關心一個問題,feign呼叫服務的時候是如何抉擇的?上一篇主要是從讀原始碼的角度入手,後續將會逐步從軟體構架方面進行剖析。 ### 一、ReflectiveFeign.FeignInvocationHandler 從上文知道fe

服務通訊之ribbon實現原理

## 前言 上一篇我們知道了feign呼叫實現負載均衡是通過整合ribbon實現的。也較為詳細的瞭解到了整合的過程。現在我們看一下ribbo是如何實現負載均衡的。寫到這裡我尚未去閱讀原始碼,我在這裡盲猜一下: 他肯定是有一個從註冊中心拉取配置的模組,一個選擇呼叫服務的模組。然後我們就帶著這樣的指導思想去看原始

服務通訊之feign的配置隔離

### 前言 由上文我們知道針對某一個Feign介面,我們可以給他設定特定的配置類。那如果現在有一個服務,我們只想對A服務配置一個攔截器攔截請求而不影響其他服務,那應該怎麼做呢? ### 一、feign介面配置 由前面的文章我們知道了feign的代理過程以及呼叫過程。現在我們看一下feign都有哪些配置?

gRPC-服務通訊實踐

##微服務間通訊常見的兩種方式 由於微服務架構慢慢被更多人使用後,迎面而來的問題是如何做好微服務間通訊的方案。我們先分析下目前最常用的兩種服務間通訊方案。 ###gRPC(rpc遠端呼叫) 場景:A服務主動發起請求到B服務,同步方式 範圍:只在微服務間通訊應用 ###EventBus(基於訊息佇列的整合事

Chris Richardson服務翻譯:構建服務服務架構的進程通訊

標記 pac blog ural action 客戶端 靈活 dso 不兼容 Chris Richardson 微服務系列翻譯全7篇鏈接: 微服務介紹 構建微服務之使用API網關 構建微服務之微服務架構的進程通訊(本文) 微服務架構中的服務發現 微服務之事件驅動的數據管理

服務spring cloud—Hystrix簡介和通過方式整合H

Hystrix簡介 Hystrix是由Netflix開源的延遲和容錯庫,用於隔離訪問遠端系統、服務或者第三方庫,防止級聯失敗,從而提升系統的可用性與容錯性。Hystrix主要通過以下幾點實現延遲和容錯。 包裹請求:使用HystrixCommand(或HystrixObservable

GO-Grpc服務開發二 服務呼叫for php

GO-Grpc微服務開發二 服務呼叫for php 參考文件列表 一.環境搭建 1.安裝grpc擴充套件 2.下載protoc命令 3.安裝PHP GRpc SDK 二.通過protoc檔案

GO-Grpc服務開發四 服務呼叫for php

GO-Grpc微服務開發四 服務呼叫for php 參考文件列表 一.環境搭建 1.安裝grpc擴充套件 2.下載protoc命令 3.安裝PHP GRpc SDK 二.通過protoc檔案

GO-Grpc服務開發二 服務編寫

GO-Grpc微服務開發二 服務編寫 服務編寫 1.定義proto檔案 2.將定義的proto編譯為go檔案 3.編寫服務 微服務執行 (本地環境示例) 啟動consul 啟動並註冊服務

GO-Grpc服務開發一 概覽

GO-Grpc微服務開發一 概覽 概覽 專案地址 主要依賴/工具 目錄結構 概覽 專案地址 [email protected]:juelite/micro-srv.git 主要依賴/工具

服務之間是如何獨立通訊的?

微服務通訊機制 系統中的各個微服務可被獨立部署,各個微服務之間是鬆耦合的。每個微服務僅關注於完成一件任務並很好地完成該任務。 圍繞業務能力組織服務、自動化部署、智慧端點、對語言及資料的去集中化控制。 將元件定義為可被獨立替換和升級的軟體單元。 以業務能力為出發點組織服務的策

基於場景選擇服務的API正規化:REST、GraphQL、Webhooks和gRPC

看過了太多關於REST的熱愛和斷言,我們有時會忘記,這隻諸多選擇之一。REST對於相當大範疇的API來說是一個非常好的標準,但在一些需要API設計風格更細緻入微的場景,還有其他的標準可供選擇。 為了幫助API開發者瞭解使用哪種API設計風格以及在什麼情況下使用,我們把REST與其他三種選擇放在一起進行了一個