本文的例子代碼在: https://github.com/grpc/grpc-go/tree/master/examples/route_guide
功能就類似目前LBS一樣,在每個位置上報一些文字信息, 上報方式有多種。
在 .proto 文件中定義服務
在 .proto 文件中定義一個服務很簡單, 就像如下的代碼:
service RouteGuide { ... }
定義rpc的方法,需要指定他們的 request 和response 類型。gRPC 可以定義四種類型的方法,這個 RouteGuide 服務例子中都會出現。
1、就像普通函數調用一樣,
客戶端帶着 stub 發送請求,然后等服務器端返回。
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A simple RPC.
//
// Obtains the feature at a given position.
//
// If no feature is found for the given point, a feature with an empty name
// should be returned.
rpc GetFeature(Point) returns (Feature) {}
2、服務器端返回的是個RPC的流
客戶端發送請求到服務器端,並獲得一個流讀取消息的序列。 客戶端從返回的流中讀取數據。 注意這里用了 stream 這個關鍵字。
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
3、客戶端用流傳輸,服務器端正常。
客戶端將消息寫入流的序列,並將它們發送到服務器。一旦客戶端已經寫完了消息,客戶端等待服務器讀取所有這些,返回其響應。
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
4、服務器和客戶端都用流來處理,即雙向流
兩個流獨立運行,所以客戶端和服務器端都可以讀取和寫入任何他們喜歡的東西。
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
產生 客戶端和服務器端代碼
有一個封裝好的 shell 腳本在 https://github.com/grpc/grpc-go/blob/master/codegen.sh
這個工具各種依賴的安裝方法請參考: http://www.cnblogs.com/ghj1976/p/4564133.html
我們這里執行的命令是: ./codegen.sh ./examples/route_guide/proto/route_guide.proto
這時候我們產生的文件是:
https://github.com/grpc/grpc-go/blob/master/examples/route_guide/proto/route_guide.pb.go
這個產生的文件中, 既有公共類的相關信息,也有客戶端和服務器端的代碼。
服務器端相關代碼
這部分代碼在: https://github.com/grpc/grpc-go/blob/master/examples/route_guide/server/server.go
服務器端我們要做這些事情:
- 實現上面 proto 文件產生的 服務器端接口
- 服務器端運行 rpc 服務器去監聽來自客戶端的請求, 並將它們路由到正確的服務上。
實現 RouteGuideServer 接口
我們在 route_guide.pb.go 中可以看到我們需要實現的接口:
// Server API for RouteGuide service
type RouteGuideServer interface {
// A simple RPC.
//
// Obtains the feature at a given position.
//
// If no feature is found for the given point, a feature with an empty name
// should be returned.
GetFeature(context.Context, *Point) (*Feature, error)
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
RecordRoute(RouteGuide_RecordRouteServer) error
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
RouteChat(RouteGuide_RouteChatServer) error
}
simple RPC.
GetFeature 需要根據客戶端傳入的一個點, 返回數據庫中對應的 Feature.
Server-side streaming RPC
返回所有在這個區域的 Feature。
注意,我們這里用到 stream.Send 方法發送的結果數據。在發送完成或者發送除了錯誤時,才return 結束這個函數。
Client-side streaming RPC
客戶端上通過 stream 上傳一批點, 服務器端記錄 點的個數、已知的feature數、總行駛距離、總時間消耗。
注意, 這里通過 stream.Recv 接收數據,通過 stream.SendAndClose 關閉返回流。
Bidirectional streaming RPC
服務器端接收客戶端上報的位置信息流, 針對當前一個位置,回應這個位置的已有 位置信息流。
這里用的 stream.Recv() 接收, stream.Send 發送。
開始服務
開啟服務我們做了下面步驟:
1、制定服務的監控端口, lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
2、創建一個 gRPC 服務實例 grpc.NewServer()
.
3、在gRPC 服務實例上注冊我們的服務實現 pb.RegisterRouteGuideServer(grpcServer, &routeGuideServer{})
4、調用 grpcServer.Serve(lis) 開啟服務, 我們監控的端口做阻塞等待,知道該進程被殺死或者 Stop() 方法被調用。
編譯服務器端
編譯時,由於牆的原因, 有些依賴包需要特殊下載, 相關資料請參考:
http://www.cnblogs.com/ghj1976/p/4549602.html
創建客戶端
這部分代碼可以在 https://github.com/grpc/grpc-go/blob/master/examples/route_guide/client/client.go 看到。
建立通道
要調用服務, 我們需要先創建一個 gRPC 通道 與服務器進行通訊, 我們這里通過 grpc.Dial 來指定服務器地址和端口來創建這個通道。
一旦gRPC通道建立后, 我們需要一個客戶端stub去執行RPC,這里我們使用 .proto 文件生產的 NewRouteGuideClient 方法。
調用服務器端方法
simple RPC.
調用simple RPC 就像調用一個本地方法一樣:
Server-side streaming RPC
跟服務器端接收流沒啥差別, stream.Recv() 函數去讀取。
Client-side streaming RPC
隨機產生 一些坐標點, 然后通過 stream.Send 依次發送, 隨后通過 stream.CloseAndRecv() 結束發送同時等待服務器端的返回。
Bidirectional streaming RPC
獨立開一個協程 通過 stream.Recv() 接收服務器端的內容, 同時主協程 輪流 通過 stream.Send 進行發送, 主協程完畢后, 調用 stream.CloseSend() , 並通過 waitc 來控制子協程的關閉。
程序運行效果截圖:
localhost:client ghj1976$ ./client
2015/06/11 16:13:27 Getting feature for point (409146138, -746188906)
2015/06/11 16:13:27 name:"Berkshire Valley Management Area Trail, Jefferson, NJ, USA" location:<latitude:409146138 longitude:-746188906 >
2015/06/11 16:13:27 Getting feature for point (0, 0)
2015/06/11 16:13:27 location:<>
2015/06/11 16:13:27 Looking for features within lo:<latitude:400000000 longitude:-750000000 > hi:<latitude:420000000 longitude:-730000000 >
2015/06/11 16:13:27 name:"Patriots Path, Mendham, NJ 07945, USA" location:<latitude:407838351 longitude:-746143763 >
2015/06/11 16:13:27 name:"101 New Jersey 10, Whippany, NJ 07981, USA" location:<latitude:408122808 longitude:-743999179 >
2015/06/11 16:13:27 name:"U.S. 6, Shohola, PA 18458, USA" location:<latitude:413628156 longitude:-749015468 >
2015/06/11 16:13:27 name:"5 Conners Road, Kingston, NY 12401, USA" location:<latitude:419999544 longitude:-740371136 >
2015/06/11 16:13:27 name:"Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" location:<latitude:414008389 longitude:-743951297 >
2015/06/11 16:13:27 name:"287 Flugertown Road, Livingston Manor, NY 12758, USA" location:<latitude:419611318 longitude:-746524769 >
2015/06/11 16:13:27 name:"4001 Tremley Point Road, Linden, NJ 07036, USA" location:<latitude:406109563 longitude:-742186778 >
2015/06/11 16:13:27 name:"352 South Mountain Road, Wallkill, NY 12589, USA" location:<latitude:416802456 longitude:-742370183 >
2015/06/11 16:13:27 name:"Bailey Turn Road, Harriman, NY 10926, USA" location:<latitude:412950425 longitude:-741077389 >
2015/06/11 16:13:27 name:"193-199 Wawayanda Road, Hewitt, NJ 07421, USA" location:<latitude:412144655 longitude:-743949739 >
2015/06/11 16:13:27 name:"406-496 Ward Avenue, Pine Bush, NY 12566, USA" location:<latitude:415736605 longitude:-742847522 >
2015/06/11 16:13:27 name:"162 Merrill Road, Highland Mills, NY 10930, USA" location:<latitude:413843930 longitude:-740501726 >
2015/06/11 16:13:27 name:"Clinton Road, West Milford, NJ 07480, USA" location:<latitude:410873075 longitude:-744459023 >
2015/06/11 16:13:27 name:"16 Old Brook Lane, Warwick, NY 10990, USA" location:<latitude:412346009 longitude:-744026814 >
2015/06/11 16:13:27 name:"3 Drake Lane, Pennington, NJ 08534, USA" location:<latitude:402948455 longitude:-747903913 >
2015/06/11 16:13:27 name:"6324 8th Avenue, Brooklyn, NY 11220, USA" location:<latitude:406337092 longitude:-740122226 >
2015/06/11 16:13:27 name:"1 Merck Access Road, Whitehouse Station, NJ 08889, USA" location:<latitude:406421967 longitude:-747727624 >
2015/06/11 16:13:27 name:"78-98 Schalck Road, Narrowsburg, NY 12764, USA" location:<latitude:416318082 longitude:-749677716 >
2015/06/11 16:13:27 name:"282 Lakeview Drive Road, Highland Lake, NY 12743, USA" location:<latitude:415301720 longitude:-748416257 >
2015/06/11 16:13:27 name:"330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" location:<latitude:402647019 longitude:-747071791 >
2015/06/11 16:13:27 name:"New York State Reference Route 987E, Southfields, NY 10975, USA" location:<latitude:412567807 longitude:-741058078 >
2015/06/11 16:13:27 name:"103-271 Tempaloni Road, Ellenville, NY 12428, USA" location:<latitude:416855156 longitude:-744420597 >
2015/06/11 16:13:27 name:"1300 Airport Road, North Brunswick Township, NJ 08902, USA" location:<latitude:404663628 longitude:-744820157 >
2015/06/11 16:13:27 location:<latitude:407113723 longitude:-749746483 >
2015/06/11 16:13:27 location:<latitude:402133926 longitude:-743613249 >
2015/06/11 16:13:27 location:<latitude:400273442 longitude:-741220915 >
2015/06/11 16:13:27 location:<latitude:411236786 longitude:-744070769 >
2015/06/11 16:13:27 name:"211-225 Plains Road, Augusta, NJ 07822, USA" location:<latitude:411633782 longitude:-746784970 >
2015/06/11 16:13:27 location:<latitude:415830701 longitude:-742952812 >
2015/06/11 16:13:27 name:"165 Pedersen Ridge Road, Milford, PA 18337, USA" location:<latitude:413447164 longitude:-748712898 >
2015/06/11 16:13:27 name:"100-122 Locktown Road, Frenchtown, NJ 08825, USA" location:<latitude:405047245 longitude:-749800722 >
2015/06/11 16:13:27 location:<latitude:418858923 longitude:-746156790 >
2015/06/11 16:13:27 name:"650-652 Willi Hill Road, Swan Lake, NY 12783, USA" location:<latitude:417951888 longitude:-748484944 >
2015/06/11 16:13:27 name:"26 East 3rd Street, New Providence, NJ 07974, USA" location:<latitude:407033786 longitude:-743977337 >
2015/06/11 16:13:27 location:<latitude:417548014 longitude:-740075041 >
2015/06/11 16:13:27 location:<latitude:410395868 longitude:-744972325 >
2015/06/11 16:13:27 location:<latitude:404615353 longitude:-745129803 >
2015/06/11 16:13:27 name:"611 Lawrence Avenue, Westfield, NJ 07090, USA" location:<latitude:406589790 longitude:-743560121 >
2015/06/11 16:13:27 name:"18 Lannis Avenue, New Windsor, NY 12553, USA" location:<latitude:414653148 longitude:-740477477 >
2015/06/11 16:13:27 name:"82-104 Amherst Avenue, Colonia, NJ 07067, USA" location:<latitude:405957808 longitude:-743255336 >
2015/06/11 16:13:27 name:"170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" location:<latitude:411733589 longitude:-741648093 >
2015/06/11 16:13:27 name:"1270 Lakes Road, Monroe, NY 10950, USA" location:<latitude:412676291 longitude:-742606606 >
2015/06/11 16:13:27 name:"509-535 Alphano Road, Great Meadows, NJ 07838, USA" location:<latitude:409224445 longitude:-748286738 >
2015/06/11 16:13:27 name:"652 Garden Street, Elizabeth, NJ 07202, USA" location:<latitude:406523420 longitude:-742135517 >
2015/06/11 16:13:27 name:"349 Sea Spray Court, Neptune City, NJ 07753, USA" location:<latitude:401827388 longitude:-740294537 >
2015/06/11 16:13:27 name:"13-17 Stanley Street, West Milford, NJ 07480, USA" location:<latitude:410564152 longitude:-743685054 >
2015/06/11 16:13:27 name:"47 Industrial Avenue, Teterboro, NJ 07608, USA" location:<latitude:408472324 longitude:-740726046 >
2015/06/11 16:13:27 name:"5 White Oak Lane, Stony Point, NY 10980, USA" location:<latitude:412452168 longitude:-740214052 >
2015/06/11 16:13:27 name:"Berkshire Valley Management Area Trail, Jefferson, NJ, USA" location:<latitude:409146138 longitude:-746188906 >
2015/06/11 16:13:27 name:"1007 Jersey Avenue, New Brunswick, NJ 08901, USA" location:<latitude:404701380 longitude:-744781745 >
2015/06/11 16:13:27 name:"6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" location:<latitude:409642566 longitude:-746017679 >
2015/06/11 16:13:27 name:"1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" location:<latitude:408031728 longitude:-748645385 >
2015/06/11 16:13:27 name:"367 Prospect Road, Chester, NY 10918, USA" location:<latitude:413700272 longitude:-742135189 >
2015/06/11 16:13:27 name:"10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" location:<latitude:404310607 longitude:-740282632 >
2015/06/11 16:13:27 name:"11 Ward Street, Mount Arlington, NJ 07856, USA" location:<latitude:409319800 longitude:-746201391 >
2015/06/11 16:13:27 name:"300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" location:<latitude:406685311 longitude:-742108603 >
2015/06/11 16:13:27 name:"43 Dreher Road, Roscoe, NY 12776, USA" location:<latitude:419018117 longitude:-749142781 >
2015/06/11 16:13:27 name:"Swan Street, Pine Island, NY 10969, USA" location:<latitude:412856162 longitude:-745148837 >
2015/06/11 16:13:27 name:"66 Pleasantview Avenue, Monticello, NY 12701, USA" location:<latitude:416560744 longitude:-746721964 >
2015/06/11 16:13:27 location:<latitude:405314270 longitude:-749836354 >
2015/06/11 16:13:27 location:<latitude:414219548 longitude:-743327440 >
2015/06/11 16:13:27 name:"565 Winding Hills Road, Montgomery, NY 12549, USA" location:<latitude:415534177 longitude:-742900616 >
2015/06/11 16:13:27 name:"231 Rocky Run Road, Glen Gardner, NJ 08826, USA" location:<latitude:406898530 longitude:-749127080 >
2015/06/11 16:13:27 name:"100 Mount Pleasant Avenue, Newark, NJ 07104, USA" location:<latitude:407586880 longitude:-741670168 >
2015/06/11 16:13:27 name:"517-521 Huntington Drive, Manchester Township, NJ 08759, USA" location:<latitude:400106455 longitude:-742870190 >
2015/06/11 16:13:27 location:<latitude:400066188 longitude:-746793294 >
2015/06/11 16:13:27 name:"40 Mountain Road, Napanoch, NY 12458, USA" location:<latitude:418803880 longitude:-744102673 >
2015/06/11 16:13:27 location:<latitude:414204288 longitude:-747895140 >
2015/06/11 16:13:27 location:<latitude:414777405 longitude:-740615601 >
2015/06/11 16:13:27 name:"48 North Road, Forestburgh, NY 12777, USA" location:<latitude:415464475 longitude:-747175374 >
2015/06/11 16:13:27 location:<latitude:404062378 longitude:-746376177 >
2015/06/11 16:13:27 location:<latitude:405688272 longitude:-749285130 >
2015/06/11 16:13:27 location:<latitude:400342070 longitude:-748788996 >
2015/06/11 16:13:27 location:<latitude:401809022 longitude:-744157964 >
2015/06/11 16:13:27 name:"9 Thompson Avenue, Leonardo, NJ 07737, USA" location:<latitude:404226644 longitude:-740517141 >
2015/06/11 16:13:27 location:<latitude:410322033 longitude:-747871659 >
2015/06/11 16:13:27 location:<latitude:407100674 longitude:-747742727 >
2015/06/11 16:13:27 name:"213 Bush Road, Stone Ridge, NY 12484, USA" location:<latitude:418811433 longitude:-741718005 >
2015/06/11 16:13:27 location:<latitude:415034302 longitude:-743850945 >
2015/06/11 16:13:27 location:<latitude:411349992 longitude:-743694161 >
2015/06/11 16:13:27 name:"1-17 Bergen Court, New Brunswick, NJ 08901, USA" location:<latitude:404839914 longitude:-744759616 >
2015/06/11 16:13:27 name:"35 Oakland Valley Road, Cuddebackville, NY 12729, USA" location:<latitude:414638017 longitude:-745957854 >
2015/06/11 16:13:27 location:<latitude:412127800 longitude:-740173578 >
2015/06/11 16:13:27 location:<latitude:401263460 longitude:-747964303 >
2015/06/11 16:13:27 location:<latitude:412843391 longitude:-749086026 >
2015/06/11 16:13:27 location:<latitude:418512773 longitude:-743067823 >
2015/06/11 16:13:27 name:"42-102 Main Street, Belford, NJ 07718, USA" location:<latitude:404318328 longitude:-740835638 >
2015/06/11 16:13:27 location:<latitude:419020746 longitude:-741172328 >
2015/06/11 16:13:27 location:<latitude:404080723 longitude:-746119569 >
2015/06/11 16:13:27 location:<latitude:401012643 longitude:-744035134 >
2015/06/11 16:13:27 location:<latitude:404306372 longitude:-741079661 >
2015/06/11 16:13:27 location:<latitude:403966326 longitude:-748519297 >
2015/06/11 16:13:27 location:<latitude:405002031 longitude:-748407866 >
2015/06/11 16:13:27 location:<latitude:409532885 longitude:-742200683 >
2015/06/11 16:13:27 location:<latitude:416851321 longitude:-742674555 >
2015/06/11 16:13:27 name:"3387 Richmond Terrace, Staten Island, NY 10303, USA" location:<latitude:406411633 longitude:-741722051 >
2015/06/11 16:13:27 name:"261 Van Sickle Road, Goshen, NY 10924, USA" location:<latitude:413069058 longitude:-744597778 >
2015/06/11 16:13:27 location:<latitude:418465462 longitude:-746859398 >
2015/06/11 16:13:27 location:<latitude:411733222 longitude:-744228360 >
2015/06/11 16:13:27 name:"3 Hasta Way, Newton, NJ 07860, USA" location:<latitude:410248224 longitude:-747127767 >
2015/06/11 16:13:27 Traversing 34 points.
2015/06/11 16:13:27 Route summary: point_count:34 distance:307771635
2015/06/11 16:13:27 Got message First message at point(0, 1)
2015/06/11 16:13:27 Got message Second message at point(0, 2)
2015/06/11 16:13:27 Got message Third message at point(0, 3)
2015/06/11 16:13:27 Got message First message at point(0, 1)
2015/06/11 16:13:27 Got message Fourth message at point(0, 1)
2015/06/11 16:13:27 Got message Second message at point(0, 2)
2015/06/11 16:13:27 Got message Fifth message at point(0, 2)
2015/06/11 16:13:27 Got message Third message at point(0, 3)
2015/06/11 16:13:27 Got message Sixth message at point(0, 3)
localhost:client ghj1976$
參考資料:
gRPC Basics: Go
https://github.com/grpc/grpc-common/blob/master/go/gotutorial.md