golang 微服務


一、 認識微服務

  1.      行業背景

             不同行業 IT 系統更新頻率

  

      IT 系統存在的問題

  

          微服務架構在企業中應用情況

   

    docker 在企業中的使用情況(容器)  

        

 

 

 

 2.      什么是微服務

    使用一套小服務來開發單個應用的方式,每個服務運行在獨立的進程里,一般采用

    輕量級的通訊機制互聯,並且它們可以通過自動化的方式部署

    什么叫微?

    代碼量少?開發時間少?微是設計思想

 

 

 3.      微服務的特點

    單一職責:獨立的業務單獨放在一個項目里,比如訂單服務作為一個項目輕量級的通信:http,rpc,非輕量級(例如 java 的 RMI)

    隔離性:每個服務相互隔離,不干擾有自己的數據

    技術多樣性

 

 

4.      微服務誕生背景

    互聯網行業的快速發展,需求變化快,用戶數量變化快

    敏捷開發深入人心,用最小的代價,做最快的迭代,頻繁修改、測試、上線容器技術的成熟,是微服務的技術基礎

 

 

 5.      互聯網架構演進之路

     

  

    單體架構

    所有功能集成在一個項目中

        項目整個打包,可以部署到服務器運行應用與數據庫可以分開部署,提高性能

        優點:

              小項目的首選,開發成本低,架構簡單

        缺點:

              項目復雜之后,很難擴展和維護擴展成本高,有瓶頸

              技術棧受限 

                 

 

 

    垂直架構

         對於單體架構的拆分,大項目拆成單個的項目結構存在數據冗余

         項目之間要處理數據同步,通過數據庫同步

         優點:

                小項目的首選,架構簡單避免單體架構的無限擴大技術不再受限了

         缺點:

                很多功能放在一個工程中,有一定瓶頸

     系統性能擴展要通過集群結點擴展,成本較高

 

              

 

 

 

     SOA 架構(面向服務的架構)

         將重復性的功能進行抽取,抽取成對應的服務通過 ESB 服務總線去訪問

         優點:

                  提高系統可重用性

                  ESB 減少系統接口耦合問題

         缺點:

                  系統與服務界限模糊,不利於開發

                  ESB 服務接口協議不固定,不利於系統維護抽取粒度較大,有一些耦合性

 

          

 

 

 

 

     微服務架構

         將服務層一個一個抽取為微服務遵循單一原則

         微服務之間采用一些輕量協議傳輸數據

         優點:

                服務拆分粒度非常細,利於開發提高系統可維護性

                比 ESB 更輕量

                適用於互聯網更新換代快的情況

         缺點:

                服務過多,服務治理成本高開發技術要求更高

 

             

 

 

 

 

 

 

 

 

 

 6.      微服務架構圖

      假設做一個商城網站

      用戶可以登錄和注冊,發短信驗證

      管理員可以查看商品,對商品增刪改查傳統訪問方式如下:

 

            

 

 

 

         微服務架構訪問方式:

           

 

 

 

 

           添加 ApiGeteway,對客戶端暴露一套 API,方便調用 

                

 

 

 

 

7.      微服務架構的優勢

     獨立性

            使用者容易理解

            技術棧靈活

     高效團隊

 

 

 

8.      微服務架構的不足 

     額外的工作,

     服務的拆分保證數據一致性

     增加了溝通成本

 

 

 

 

二、 微服務需要考慮的問題

1.  微服務如何通信

                              從通信模式考慮

 

一對一

一對多

同步

最常見

 

異步

通知-請求異步響應

發布訂閱-發布異步響應

 

 

                            從通信協議考慮

                             RPC

 

 

 

2. 微服務 如何 發現 彼此

     傳統服務如下:

           一般是 IP:端口號訪問

          

       微服務服務發現有 2 種方式——客戶端發現和服務端發現

            客戶端發現:

                 微服務啟動后,將自己 IP 和端口進行注冊,客戶端查詢注冊,得到提供服務的 IP 和端口,通過負載均衡,訪問微服務

         

 

 

 

        服務端發現:

             客戶端訪問時,不去注冊中心了,通過服務發現代理去直接訪問

 

                

 

 

 

 

 

 3.      微服務如何部署、更新和擴容

            

         微服務部署到 docker 容器

         涉及服務編排:K8S,swarm

 

 

  

三、 RPC

      1.      RPC 簡介

             遠程過程調用(Remote Procedure Call,RPC)是一個計算機通信協議

             該協議允許運行於一台計算機的程序調用另一台計算機的子程序,而程序員無需額外地為這個交互作用編程

             如果涉及的軟件采用面向對象編程,那么遠程過程調用亦可稱作遠程調用或遠程方法調用

 

 

       2.      流行 RPC 框架的對比

            

 

 

 

        3.      golang 中如何實現 RPC

                golang 中實現 RPC 非常簡單,官方提供了封裝好的庫,還有一些第三方的庫

                golang 官方的 net/rpc 庫使用 encoding/gob 進行編解碼,支持 tcp 和 http 數據傳輸方式,由於其他語言不支持 gob 編解碼方式,

                所以 golang 的 RPC 只支持 golang 開發的服務器與客戶端之間的交互

                官方還提供了 net/rpc/jsonrpc 庫實現 RPC 方法,jsonrpc 采用 JSON 進行數據編解碼,因而支持跨語言調用,目前 jsonrpc 庫是基於 tcp 協議實現的,暫不支持 http 傳輸方式

                golang 的 RPC 必須符合 4 個條件才可以

                      1. 結構體字段首字母要大寫,要跨域訪問,所以大寫

                      2. 函數名必須首字母大寫(可以序列號導出的)

                      3. 函數第一個參數是接收參數,第二個參數是返回給客戶端參數,必須是指針類型

                      4. 函數必須有一個返回值 error

                另外,net/rpc/jsonrpc 庫通過 json 格式編解碼,支持跨語言調用

 

 

        4.      RPC 調用流程

                  微服務架構下數據交互一般是對內 RPC,對外 REST

               

 

 

 

                 將業務按功能模塊拆分到各個微服務,具有提高項目協作效率、降低模塊耦合度、提高系統可用性等優點,但是開發門檻比較高,

                 比如 RPC 框架的使用、后期的服務監控等工作

                一般情況下,我們會將功能代碼在本地直接調用,微服務架構下,我們需要將這個函數作為單獨的服務運行,客戶端通過網絡調用

 

 

      5.      網絡傳輸數據格式

                

                成熟的 RPC 框架會有自定義傳輸協議,這里網絡傳輸格式定義如下,前面是固定長度消息頭,后面是變長消息體

                  

 

 

 

 

        6.      實現 RPC 服務端

                 服務端接收到的數據需要包括什么?

                 調用的函數名、參數列表 

                 一般會約定函數的第二個返回值是 error 類型通過反射實現

                 服務端需要解決的問題是什么?

                 Client 調用時只傳過來函數名,需要維護函數名到函數之間的 map 映射服務端的核心功能有哪些?

                 維護函數名到函數反射值的 map

                 client 端傳函數名、參數列表后,服務端要解析為反射值,調用執行函數的返回值打包,並通過網絡返回給客戶端

 

 

          7.      實現 RPC 客戶端

 

                 客戶端只有函數原型,使用 reflect.MakeFunc()  可以完成原型到函數的調用

                 reflect.MakeFunc()是 Client 從函數原型到網絡調用的關鍵

 

 

           8.      實現 RPC 通信測試

                  給服務端注冊一個查詢用戶的方法,客戶端去 RPC 調用

 

 

 

 

四、 gRPC 入門

           1.      gRPC 簡介

                   gRPC 由 google 開發,是一款語言中立、平台中立、開源的遠程過程調用系統

                   gRPC 客戶端和服務端可以在多種環境中運行和交互,例如用 java 寫一個服務端,可以用 go 語言寫客戶端調用

 

          2.      gRPC Protobuf 介紹

                  微服務架構中,由於每個服務對應的代碼庫是獨立運行的,無法直接調用,彼此間的通信就是個大問題

                  gRPC 可以實現微服務,將大的項目拆分為多個小且獨立的業務模塊,也就是服務,各服務間使用高效的 protobuf 協議進行 RPC 調用,gRPC 默認使用 protocol buffers,

                  這是 google 開源的一套成熟的結構數據序列化機制(當然也可以使用其他數據格式如 JSON)

                  可以用 proto files 創建 gRPC 服務,用 message 類型來定義方法參數和返回類型

 

          3.      安裝 gRPC Protobuf

                 

     go get -u -v github.com/golang/protobuf/proto 
go
get google.golang.org/grpc(無法使用,用如下命令代替) git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text go get -u github.com/golang/protobuf/{proto,protoc-gen-go} git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto
cd $GOPATH/src/ go install google.golang.org/grpc go get github.com/golang/protobuf/protoc-gen-go

 

 

                 上面安裝好后,會在 GOPATH/bin 下生成 protoc-gen-go.exe

                 但還需要一個 protoc.exe,windows 平台編譯受限,很難自己手動編譯,直接去網站下載一個,

                 地址:https://github.com/protocolbuffers/protobuf/releases/tag/v3.9.0

                 同樣放到 GOPATH/bin 下

 

 

 

 

五、 Protobuf 語法

 

        1.      基本規范

                 文件以.proto 做為文件后綴,除結構定義外的語句以分號結尾

                 結構定義可以包含:message、service、enum

                 rpc 方法定義結尾的分號可有可無

 

                 Message 命名采用駝峰命名方式,字段命名采用小寫字母加下划線分隔方式

message SongServerRequest {
    required string song_name = 1;
}

 

                 Enums 類型名采用駝峰命名方式,字段命名采用大寫字母加下划線分隔方式

enum Foo {
    FIRST_VALUE = 1; SECOND_VALUE = 2;
}

                  Service 與 rpc 方法名統一采用駝峰式命名

 

 

 

           2.      字段規則

                    字段格式:限定修飾符 | 數據類型 | 字段名稱 | = | 字段編碼值 | [字段默認值]

                    限定修飾符包含 required\optional\repeated

                        Required: 

                            表示是一個必須字段,必須相對於發送方,在發送消息之前必須設置該字段的值,對於接收方,必須能夠識別該字段的意思。

                            發送之前沒有設置 required 字段或者無法識別 required 字段都會引發編解碼異常,導致消息被丟棄

 

                       Optional:

                            表示是一個可選字段,可選對於發送方,在發送消息時,可以有選擇性的設置或者不設置該字段的值。

                            對於接收方,如果能夠識別可選字段就進行相應的處理,如果無法識別,則忽略該字段,消息中的其它字段正常處理。

                           ---因為 optional 字段的特性,很多接口在升級版本中都把后來添加的字段都統一的設置為 optional 字段,

                           這樣老的版本無需升級程序也可以正常的與新的軟件進行通信,只不過新的字段無法識別而已,

                           因為並不是每個節點都需要新的功能,因此可以做到按需升級和平滑過渡

 

                      Repeated:

                           表示該字段可以包含 0~N 個元素。其特性和 optional 一樣,但是每一次可以包含多個值。可以看作是在傳遞一個數組的值

 

 

                    數據類型

                            Protobuf 定義了一套基本數據類型。幾乎都可以映射到 C++\Java 等語言的基礎數據類型

 

 

 

 

            N  表示打包的字節並不是固定。而是根據數據的大小或者長度 

            關於 fixed32 和 int32 的區別。fixed32 的打包效率比 int32 的效率高,但是使用的空間一般比 int32 多。因此一個屬於時間效率高,一個屬於空間效率高

 

            字段名稱

                 字段名稱的命名與 C、C++、Java 等語言的變量命名方式幾乎是相同的

                 protobuf 建議字段的命名采用以下划線分割的駝峰式。例如 first_name 而不是 firstName

 

           字段編碼值

                 有了該值,通信雙方才能互相識別對方的字段,相同的編碼值,其限定修飾符和數據類型必須相同,編碼值的取值范圍為 1~2^32(4294967296)

                 其中 1~15 的編碼時間和空間效率都是最高的,編碼值越大,其編碼的時間和空間效率就越低,所以建議把經常要傳遞的值把其字段編碼設置為 1-15 之間的值

                1900~2000 編碼值為 Google protobuf 系統內部保留值,建議不要在自己的項目中使用

 

          字段默認值

                 當在傳遞數據時,對於 required 數據類型,如果用戶沒有設置值,則使用默認值傳遞到對端

 

 

         3.      service 如何定義

               如果想要將消息類型用在 RPC 系統中,可以在.proto 文件中定義一個 RPC 服務接口,protocol buffer 編譯器會根據所選擇的不同語言生成服務接口代碼

               例如,想要定義一個 RPC 服務並具有一個方法,該方法接收 SearchRequest 並返回一個 SearchResponse,此時可以在.proto 文件中進行如下定義:

                

service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse) {}
}

            生成的接口代碼作為客戶端與服務端的約定,服務端必須實現定義的所有接口方法,客戶端直接調用同名方法向服務端發起請求,

            比較麻煩的是,即便業務上不需要參數也必須指定一個請求消息,一般會定義一個空 message

 

 

 

        4.      Message 如何定義

              一個 message 類型定義描述了一個請求或響應的消息格式,可以包含多種類型字段例如定義一個搜索請求的消息格式,

              每個請求包含查詢字符串、頁碼、每頁數目字段名用小寫,轉為 go 文件后自動變為大寫,message 就相當於結構體

syntax = "proto3";

message SearchRequest {
    string  query = 1;            //  查詢字符串 
    int32  page_number = 2;       //  頁碼
    int32  result_per_page = 3;   //  每頁條數
}

             首行聲明使用的 protobuf 版本為 proto3

             SearchRequest 定義了三個字段,每個字段聲明以分號結尾,.proto 文件支持雙斜線   // 添加單行注釋

 

 

 

        5.      添加更多 Message 類型

              一個.proto 文件中可以定義多個消息類型,一般用於同時定義多個相關的消息,例如在同一個.proto 文件中同時定義搜索請求和響應消息

syntax = "proto3";

//SearchRequest 搜索請求
message SearchRequest {
    string   query = 1;            //  查詢字符串
    int32    page_number = 2;      //  頁碼
    int32    result_per_page = 3;  //  每頁條數
}

 

//  SearchResponse 搜索響應
message SearchResponse {
    ...
}

 

 

          6.      如何使用其他 Message

                 message 支持嵌套使用,作為另一 message 中的字段類型

message SearchResponse {
    repeated Result results = 1;
}


message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
}

 

 

          7.      Message 嵌套的使用

                 支持嵌套消息,消息可以包含另一個消息作為其字段。也可以在消息內定義一個新的消息

                 內部聲明的 message 類型名稱只可在內部直接使用

message SearchResponse {
 
    message Result {
        string url = 1;
        string title = 2;
        repeated string snippets = 3;
    }

    repeated Result results = 1;

}

 

另外,還可以多層嵌套

message Outer { // Lev el 0
    message MiddleAA { // Level 1
        message Inner { // Level 2
            int64 ival = 1;
            bool booly = 2;
}
} message Midd leBB { // Level
1 message Inn er { // Le vel 2 int32 ival = 1; bool booly = 2
}
}
}

 

 

        8. proto3 的 Map 類型

               proto3 支持 map 類型聲明

map<key_type, value_type> map_field = N;

message Project {...}

map<string, Project> projects = 1;

              鍵、值類型可以是內置的類型,也可以是自定義 message 類型

              字段不支持 repeated 屬性

 

 

          9.  .proto 文件編譯

               

                  通過定義好的.proto 文件生成 Java, Python, C++, Go, Ruby, JavaNano, Objective-C, or C# 代碼,需要安裝編譯器 protoc

                  當使用 protocol buffer 編譯器運行.proto 文件時,編譯器將生成所選語言的代碼,用於使用在.proto 文件中定義的消息類型、服務接口約定等。

                  不同語言生成的代碼格式不同:

                      C++: 每個.proto 文件生成一個.h 文件和一個.cc 文件,每個消息類型對應一個類

                      Java:  生成一個.java  文件,同樣每個消息對應一個類,同時還有一個特殊的Builder 類用於創建消息接口

                      Python: 姿勢不太一樣,每個.proto 文件中的消息類型生成一個含有靜態描述符的模塊,該模塊與一個元類 metaclass 在運行時創建需要的 Python 數據訪問類

                      Go: 生成一個.pb.go 文件,每個消息類型對應一個結構體

                      Ruby: 生成一個.rb 文件的 Ruby 模塊,包含所有消息類型

                     JavaNano: 類似 Java,但不包含 Builder 類

                     Objective-C: 每個.proto 文件生成一個 pbobjc.h 和一個 pbobjc.m 文件

                     C#: 生成.cs 文件包含,每個消息類型對應一個類

 

 

         10. import 導入定義

                  可以使用 import 語句導入使用其它描述文件中聲明的類型

                  protobuf 接口文件可以像 C 語言的 h 文件一個,分離為多個,在需要的時候通過 import 導入需要對文件。

                  其行為和 C 語言的#include 或者 java 的 import 的行為大致相同,例如 import "others.proto";

                  protocol buffer 編譯器會在 -I / --proto_path 參數指定的目錄中查找導入的文件,如果沒有指定該參數,默認在當前目錄中查找

 

 

         11.   包的使用 

                  在.proto 文件中使用 package 聲明包名,避免命名沖突

syntax = "proto3";

package foo.bar; message Open {...}

 

                  在其他的消息格式定義中可以使用包名+消息名的方式來使用類型,如

message Foo {
    ...
    foo.bar.Open open = 1;
    ...
}

 

                  在不同的語言中,包名定義對編譯后生成的代碼的影響不同

                       C++  中:對應 C++命名空間,例如 Open 會在命名空間 foo::bar 中

                       Java  中:package 會作為 Java 包名,除非指定了 option jave_package 選項

                       Python 中:package 被忽略

                       Go 中:默認使用 package 名作為包名,除非指定了 option go_package 選項 JavaNano 中:同 Java

                       C# 中:package 會轉換為駝峰式命名空間,如 Foo.Bar,除非指定了 option csharp_namespace 選項

 

 

 

六、   Go Micro 入門

          1.      go-micro 簡介

                   Go Micro 是一個插件化的基礎框架,基於此可以構建微服務,Micro 的設計哲學

                   是可插拔的插件化架構

                   在架構之外,它默認實現了 consul 作為服務發現(2019 年源碼修改了默認使用mdns),通過 http 進行通信,通過 protobuf 和 json 進行編解碼

 

          2.      go-micro 的主要功能

                    服務發現:

                           自動服務注冊和名稱解析。服務發現是微服務開發的核心。

                           當服務 A 需要與服務 B 通話時,它需要該服務的位置。默認發現機制是多播 DNS(mdns),一種零配置系統。

                           您可以選擇使用 SWIM 協議為 p2p 網絡設置八卦,或者為彈性雲原生設置設置 consul

 

                    負載均衡:

                           基於服務發現構建的客戶端負載均衡。一旦我們獲得了服務的任意數量實例的地址,我們現在需要一種方法來決定要路由到哪個節點。

                           我們使用隨機散列負載均衡來提供跨服務的均勻分布,並在出現問題時重試不同的節點

 

                   消息編碼:

                           基於內容類型的動態消息編碼。客戶端和服務器將使用編解碼器和內容類型為您無縫編碼和解碼 Go 類型。

                           可以編碼任何種類的消息並從不同的客戶端發送。客戶端和服務器默認處理此問題。這包括默認的 protobuf 和 json

 

                  請求/響應:

                           基於 RPC 的請求/響應,支持雙向流。我們提供了同步通信的抽象。

                           對服務的請求將自動解決,負載平衡,撥號和流式傳輸。啟用 tls 時,默認傳輸為 http / 1.1 或 http2

 

                  Async Messaging:

                          PubSub 是異步通信和事件驅動架構的一流公民。事件通知是微服務開發的核心模式。

                          啟用 tls 時,默認消息傳遞是點對點 http / 1.1 或 http2

 

                 可插拔接口:

                          Go Micro 為每個分布式系統抽象使用 Go 接口,因此,這些接口是可插拔的,並允許 Go Micro 與運行時無關,可以插入任何基礎技術

                          插件地址:https://github.com/micro/go-plugins

 

 

          3.   go-micro 通信流程

                 Server 監聽客戶端的調用,和 Brocker 推送過來的信息進行處理。

                 並且 Server 端需要向 Register 注冊自己的存在或消亡,這樣 Client 才能知道自己的狀態

                 Register 服務的注冊的發現,Client 端從 Register 中得到 Server 的信息,然后每次調用都根據算法選擇一個的 Server 進行通信,

                 當然通信是要經過編碼/解碼,選擇傳輸協議等一系列過程的如果有需要通知所有的 Server 端可以使用 Brocker 進行信息的推送,Brocker 信息隊列進行信息的接收和發布

 

 

          4.      go-micro 核心接口

                   go-micro 之所以可以高度訂制和他的框架結構是分不開的,go-micro 由 8 個關鍵的 interface 組成,

                   每一個 interface 都可以根據自己的需求重新實現,這 8 個主要的 inteface 也構成了 go-micro 的框架結構

                      

 

 

 

 

 

 

 

 

八、 Go Micro 接口詳解

 

       1.  Transort 通信接口

                    服務之間通信的接口,也就是服務發送和接收的最終實現方式,是由這些接口定制的

type Socket interface {
    Recv(*Message) error
    Send(*Message) error
    Close() error
}

type Client interface {
    Socket
}

type Listener interface {
    Addr()  string
    Close() error
    Accept( func( Socket ) ) error
}

type Transport interface {
    Dial(addr string, opts ...DialOption)  (Client, error)
    Listen(addr string, opts ...ListenOption)  (Listener, error)
    String()  string
}

 

 

      2.  Codec 編碼接口

              go-micro 有很多種編碼解碼方式,默認的實現方式是 protobuf,當然也有其他的實現方式,json、jsonrpc、mercury 等等

type Codec interface {
    ReadHeader(*Message,  MessageType)  error
    ReadBody(interface{})  error
    Write(*Message,  interface{})  error
    Close()   error
    String()  string
}

 

 

     3.  Registry 注冊接口

             服務的注冊和發現,目前實現的有 consul、mdns、etcd、zookeeper、kubernetes 等

type Registry interface {
    Register(*Service, ...RegisterOption)  error
    Deregister(*Service)  error
    GetService(string)   ([]*Service, error)
    ListServices()   ([]*Service, error)
    Watch(...WatchOption)   (Watcher, error)
    String()   string
    Options()   Options
}

 

 

      4.    Selector 負載均衡

                以 Registry 為基礎,Selector 是客戶端級別的負載均衡,當有客戶端向服務發送請求時,

                selector 根據不同的算法從 Registery 中的主機列表,得到可用的 Service 節點,進行通信,目前實現的有循環算法和隨機算法,默認的是隨機算法

 

type Selector interface {

    Init(opts ...Option)  error

    Options()  Options

    // Select returns a function which should return the next node 
    Select(service string, opts ...SelectOption) (Next, error)

    // Mark sets the success/error against a node 
    Mark(service string, node *registry.Node, err error) 

// Reset returns state back to zero for a service Reset(service string) // Close renders the selector unusable Close() error // Name of the selector String() string }

 

 

     5.  Broker 發布訂閱接口

          Broker 是消息發布和訂閱的接口。

          例如,因為服務的節點是不固定的,如果需要修改所有服務行為,可以使服務訂閱某個主題,當有信息發布時,所有的監聽服務都會收到信息,根據你的需要做相應的行為即可

 

type Broker interface {

    Options()  Options
    Address()  string
    Connect()  error
    Disconnect()  error
    Init(...Option)  error
    Publish(string, *Message, ...PublishOption)  error
    Subscribe(string, Handler, ...SubscribeOption)  (Subscriber, error)
    String()  string

}

 

 

 

     6.  Client 客戶端接口

              Client 是請求服務的接口,他封裝 Transport 和 Codec 進行 rpc 調用,也封裝了 Brocker進行信息的發布

type Client interface {

    Init(...Option) error
    Options() Options
    NewMessage(topic string, msg interface{}, opts ...MessageOption) Message 
NewRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) Publish(ctx context.Context, msg Message, opts ...PublishOption) error String() string }

 

     7.  Server 服務端接口

            Server 監聽等待 rpc 請求,監聽 broker 的訂閱信息,等待信息隊列的推送等

 

type Server interface {
    Options()  Options
    Init(...Option)  error
    Handle(Handler)  error
    NewHandler(interface{}, ...HandlerOption)  Handler
    NewSubscriber(string, interface{}, ...SubscriberOption)  Subscriber
    Subscribe(Subscriber)  error
    Register()  error
    Deregister()  error
    Start()  error
    Stop()  error
    String()  string
}

 

 

      8.  Serveice 接口

              Service 是 Client 和 Server 的封裝,他包含了一系列的方法使用初始值去初始化

              Service 和 Client,使我們可以很簡單的創建一個 rpc 服務

type Service interface {
    Init(...Option)
    Options() Options
    Client() client.Client
    Server() server.Server
    Run() error
    String() string
}

 

 

 

 

 

go-micro 安裝

 

查看的網址:https://github.com/micro/

cmd 中輸入下面 3 條命令下載,會自動下載相關的很多包

    go get -u -v github.com/micro/micro

    go get -u -v github.com/micro/go-micro

    go get -u -v github.com/micro/protoc-gen-micro

 

 

 

go-micro  跨域問題

    //  RPC請求, 請求跨域
    // 設置允許的跨域地址
    if origin := r.Header.Get("Origin");true{
        w.Header().Set("Access-Control-Allow-Origin",origin)
    }
    //  設置跨越請求允許的請求方式
    w.Header().Set("Access-Control-Allow-Methods","POST,GET")
    //  設置跨越請求允許的數據格式
    w.Header().Set("Access-Control-Allow-Headers-Content-Type"," Content Length, Accept Encoding,X Token, X Client")
    //  設置跨越請求是否可攜帶證書
    w.Header().Set("Access-Control-Allow-Credentials","true")




設置允許的跨域地址

"Access-Control-Allow-Origin"

 

 

設置跨越請求允許的請求方式

"Access-Control-Allow-Methods",  "POST,GET"

 

 

設置跨越請求允許的數據格式

"Access-Control-Allow-Headers-Content-Type",   " Content Length, Accept Encoding,X Token, X Client"

 

 

設置跨越請求是否可攜帶證書

"Access-Control-Allow-Credentials"  "true"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM