gRPC初體驗

gRPC是由Google主導(dǎo)開發(fā)的RPC框架菲茬,使用HTTP/2協(xié)議并用ProtoBuf作為序列化工具坚弱。其客戶端提供Objective-C盛正、Java接口,服務(wù)器側(cè)則有Java蚁孔、Golang奶赔、C++等接口,從而為移動端(iOS/Androi)到服務(wù)器端通訊提供了一種解決方案勒虾。 當(dāng)然在當(dāng)下的環(huán)境下纺阔,這種解決方案更熱門的方式是RESTFull API接口。該方式需要自己去選擇編碼方式修然、服務(wù)器架構(gòu)笛钝、自己搭建框架(JSON-RPC)质况。gRPC官方對REST的聲音是:

  • 和REST一樣遵循HTTP協(xié)議(明確的說是HTTP/2),但是gRPC提供了全雙工流
  • 和傳統(tǒng)的REST不同的是gRPC使用了靜態(tài)路徑玻靡,從而提高性能
  • 用一些格式化的錯誤碼代替了HTTP的狀態(tài)碼更好的標(biāo)示錯誤

至于是否要選擇用gRPC结榄。對于已經(jīng)有一套方案的團(tuán)隊,可以參考下囤捻。如果是從頭來做臼朗,可以考慮下gRPC提供的從客戶端到服務(wù)器的整套解決方案,這樣不用客戶端去實現(xiàn)http的請求會話蝎土,JSON等的解析视哑,服務(wù)器端也有現(xiàn)成的框架用。從15年3月到現(xiàn)在gRPC也發(fā)展了一年了誊涯,慢慢趨于成熟挡毅。下面我們就以gRPC的Golang版本看下其在golang上面的表現(xiàn)。至于服務(wù)端的RPC暴构,感覺golang標(biāo)準(zhǔn)庫的RPC框架基本夠用了,沒必要再去用另一套方案跪呈。

1. 安裝protobuf

雖然gRPC也支持protobuf2.x,但是建議還是使用protobuf3.x取逾,盡管還沒有正式版本耗绿,不過golang版本基本沒有什么問題,另外3.x官方支持了Objective-C砾隅,這也是我們使用gRPC的初衷:提供一個移動端到服務(wù)器的解決方案误阻。去到Protocol Buffers下載最新版本(Version3.0.0 beta2),然后解壓到本地琉用。本地需要已經(jīng)安裝好autoconf automake libtool.rpm系列(fedora/centos/redheat)可以用yum安裝堕绩。Mac上可以用brew進(jìn)行安裝

brew install autoconf automake libtool

然后執(zhí)行

./configure --prefix=your_pb_install_path

接著

make 
make install
set your_pb_install_path to your $PATH

檢查是否安裝完成

protoc --version
libprotoc 3.0.0

然后安裝golang protobuf直接使用golang的get即可

go get -u github.com/golang/protobuf/proto // golang protobuf 庫
go get -u github.com/golang/protobuf/protoc-gen-go //protoc --go_out 工具

2. 安裝gRPC-go

gRPC-go可以通過golang 的get命令直接安裝,非常方便邑时。

go get google.golang.org/grpc

這里大家可能比較奇怪,為什么gRPC-go在github的地址是"https://github.com/grpc/grpc-go",但是為什么要用“google.golang.org/grpc”進(jìn)行安裝呢特姐?應(yīng)該grpc原本是google內(nèi)部的項目晶丘,歸屬golang,就放在了google.golang.org下面了唐含,后來對外開放浅浮,又將其遷移到github上面了,又因為golang比較坑爹的import路徑規(guī)則捷枯,所以就都沒有改路徑名了滚秩。

但是這樣就有個問題了。要如何去管理版本呢淮捆?這個目前我還沒有什么比較好的方法郁油,希望知道的朋友一起分享下本股。目前想到一個方法是手動下載某個版本,然后寫個腳本統(tǒng)一修改代碼中的import里面的路徑.

3. 示例程序

3.1 protobuf

該示例源自gRPC-go的examples的helloworld桐腌。先看PB的描述:

syntax = "proto3";

option objc_class_prefix = "HLW";

package helloworld;

// 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;
}

這里定義了一個服務(wù)Greeter拄显,其中有個API SayHello。其接受參數(shù)為HelloRequest類型案站,返回HelloReply類型躬审。這里HelloRequestHelloReply就是普通的PB定義

服務(wù)定義為:

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

service定義了一個server。其中的接口可以是四種類型

  • rpc GetFeature(Point) returns (Feature) {}
    類似普通的函數(shù)調(diào)用蟆盐,客戶端發(fā)送請求Point到服務(wù)器承边,服務(wù)器返回相應(yīng)Feature.
  • rpc ListFeatures(Rectangle) returns (stream Feature) {}
    客戶端發(fā)起一次請求,服務(wù)器端返回一個流式數(shù)據(jù)石挂,比如一個數(shù)組中的逐個元素
  • rpc RecordRoute(stream Point) returns (RouteSummary) {}
    客戶端發(fā)起的請求是一個流式的數(shù)據(jù)博助,比如數(shù)組中的逐個元素,服務(wù)器返回一個相應(yīng)
  • rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
    客戶端發(fā)起的請求是一個流式數(shù)據(jù)誊稚,比如數(shù)組中的逐個元素翔始,二服務(wù)器返回的也是一個類似的數(shù)據(jù)結(jié)構(gòu)

后面三種可以參考官方的route_guide示例。

使用protoc命令生成相關(guān)文件:

protoc --go_out=plugins=grpc:. helloworld.proto
ls
helloworld.pb.go    helloworld.proto

生成對應(yīng)的pb.go文件里伯。這里用了plugins選項城瞎,提供對grpc的支持,否則不會生成Service的接口疾瓮。

3.2 服務(wù)器端程序

然后編輯服務(wù)器端程序:

package main

import (
    "log"
    "net"

    pb "your_path_to_gen_pb_dir/helloworld"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    s.Serve(lis)
}

這里首先定義一個server結(jié)構(gòu)脖镀,然后實現(xiàn)SayHello的接口,其定義在“your_path_to_gen_pb_dir/helloworld”

SayHello(context.Context, *HelloRequest) (*HelloReply, error)

然后調(diào)用grpc.NewServer() 創(chuàng)建一個server s狼电。接著注冊這個server s到結(jié)構(gòu)server上面 pb.RegisterGreeterServer(s, &server{}) 最后將創(chuàng)建的net.Listener傳給s.Serve()蜒灰。就可以開始監(jiān)聽并服務(wù)了,類似HTTP的ListenAndServe肩碟。

3.3 客戶端程序

客戶端程序:

package main

import (
    "log"
    "os"

    pb "your_path_to_gen_pb_dir/helloworld"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
)

func main() {
    // Set up a connection to the server.
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}

這里通過pb.NewGreeterClient()傳入一個conn創(chuàng)建一個client强窖,然后直接調(diào)用client上面對應(yīng)的服務(wù)器的接口

SayHello(context.Context, *HelloRequest) (*HelloReply, error)

接口,返回*HelloReply 對象削祈。

先運(yùn)行服務(wù)器翅溺,在運(yùn)行客戶端,可以看到髓抑。

./greeter_server &

./greeter_client
2016/03/10 21:42:19 Greeting: Hello world
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咙崎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吨拍,更是在濱河造成了極大的恐慌褪猛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羹饰,死亡現(xiàn)場離奇詭異伊滋,居然都是意外死亡碳却,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門新啼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來追城,“玉大人,你說我怎么就攤上這事燥撞∽” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵物舒,是天一觀的道長色洞。 經(jīng)常有香客問我,道長冠胯,這世上最難降的妖魔是什么火诸? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮荠察,結(jié)果婚禮上置蜀,老公的妹妹穿的比我還像新娘。我一直安慰自己悉盆,他們只是感情好盯荤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著焕盟,像睡著了一般秋秤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脚翘,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天灼卢,我揣著相機(jī)與錄音,去河邊找鬼来农。 笑死鞋真,一個胖子當(dāng)著我的面吹牛忌锯,可吹牛的內(nèi)容都是我干的限书。 我是一名探鬼主播诅炉,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼泞辐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了据某?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蒋困,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敬辣,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雪标,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年零院,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片村刨。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡告抄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嵌牺,到底是詐尸還是另有隱情打洼,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布逆粹,位于F島的核電站募疮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏僻弹。R本人自食惡果不足惜阿浓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹋绽。 院中可真熱鬧芭毙,春花似錦、人聲如沸卸耘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹊奖。三九已至苛聘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忠聚,已是汗流浹背设哗。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留两蟀,地道東北人网梢。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像赂毯,于是被迫代替她去往敵國和親战虏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理党涕,服務(wù)發(fā)現(xiàn)烦感,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 1)簡介 gRPC負(fù)載平衡的主要實現(xiàn)機(jī)制是外部負(fù)載平衡膛堤,即通過外部負(fù)載平衡器來向客戶端提供更新后的服務(wù)器列表手趣。 g...
    Jay_Guo閱讀 13,227評論 6 22
  • 主要基于官網(wǎng)介紹的文檔總結(jié)而來。 需要先了解 protocol buffers 為什么使用gRPC 通過gPRC肥荔,...
    kingeasternsun閱讀 3,634評論 1 4
  • GRPC是基于protocol buffers3.0協(xié)議的. 本文將向您介紹gRPC和protocol buffe...
    二月_春風(fēng)閱讀 17,977評論 2 28
  • 1.先總后分理清思路 “領(lǐng)導(dǎo)绿渣,因為王經(jīng)理上午出差去了朝群,他要出差2天;然后小李家中有事中符,他要休假一天姜胖;趙主任恰巧下午...
    咿呀作語閱讀 265評論 2 5