GRPC源碼實例解析(一)——UnaryRPC Server 篇

本文以官方提供的入門的demo helloworld(https://github.com/grpc/grpc-go/tree/master/examples/helloworld/helloworld)為例宋距,通過源碼講解實際的grpc調(diào)用執(zhí)行的流程(UnaryRPC)轴踱,為了方便理解只列出核心代碼。該篇主要關(guān)注Server端源代碼流程谚赎。

RegisterGreeterServer實際將helloworld.proto 中定義的Greeter_Service進行注冊淫僻,所謂的服務注冊。

service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}
var Greeter_ServiceDesc = grpc.ServiceDesc{
    ServiceName: "helloworld.Greeter",
    HandlerType: (*GreeterServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "SayHello",
            Handler:    _Greeter_SayHello_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "examples/helloworld/helloworld/helloworld.proto",
}
func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) {
    s.RegisterService(&Greeter_ServiceDesc, srv)
}
func (s *Server) register(sd *ServiceDesc, ss interface{}) {
    info := &serviceInfo{
        serviceImpl: ss,
        methods:     make(map[string]*MethodDesc),
        streams:     make(map[string]*StreamDesc),
        mdata:       sd.Metadata,
    }
    for i := range sd.Methods {
        d := &sd.Methods[i]
        info.methods[d.MethodName] = d
    }
    s.services[sd.ServiceName] = info
}

Serve方法通過lis net.Listener監(jiān)聽連接壶唤,每次起一新的goroutine來處理 新的Conn雳灵,每一個新的連接都是在獨立的線程中進行處理并發(fā)執(zhí)行。

func (s *Server) Serve(lis net.Listener) error {
    for {
        rawConn, err := lis.Accept()
        go func() {
            s.handleRawConn(lis.Addr().String(), rawConn)
        }()
    }
}

建立一個HTTP2的Transport闸盔,用其進行Transport層的rpc調(diào)用執(zhí)行

func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
    st := s.newHTTP2Transport(conn, authInfo)
    go func() {
        s.serveStreams(st)
    }()
}
func (s *Server) serveStreams(st transport.ServerTransport) {
    s.handleStream(st, stream, s.traceInfo(st, stream))
}

通過stream.Method()得到需要調(diào)用FullMethod(/helloworld.Greeter/SayHello)從注冊的services列表中找到對應serviceInfo對象悯辙,進而找到MethodDesc,然后執(zhí)行processUnaryRPC

func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) {
    srv, knownService := s.services[service]
    if knownService {
        if md, ok := srv.methods[method]; ok {
            s.processUnaryRPC(t, stream, srv, md, trInfo)
            return
        }
    }

}
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, info *serviceInfo, md *MethodDesc, trInfo *traceInfo) (err error) {
    // 實際執(zhí)行定義的rpc方法google.golang.org/grpc/examples/helloworld/helloworld._Greeter_SayHello_Handler(如下)
    reply, appErr := md.Handler(info.serviceImpl, ctx, df, s.opts.unaryInt)
    //將rpc方法的值返回給客戶端
    s.sendResponse(t, stream, reply, cp, opts, comp)
}

google.golang.org/grpc/examples/helloworld/helloworld._Greeter_SayHello_Handler

func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(HelloRequest)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(GreeterServer).SayHello(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/helloworld.Greeter/SayHello",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
    }
    return interceptor(ctx, in, info, handler)
}

GRPC源碼實例解析(二)
http://www.reibang.com/p/944e3eb59dd8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迎吵,一起剝皮案震驚了整個濱河市躲撰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌击费,老刑警劉巖拢蛋,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔫巩,居然都是意外死亡谆棱,警方通過查閱死者的電腦和手機瞬铸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來础锐,“玉大人,你說我怎么就攤上這事荧缘〗跃” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵截粗,是天一觀的道長信姓。 經(jīng)常有香客問我,道長绸罗,這世上最難降的妖魔是什么意推? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮珊蟀,結(jié)果婚禮上菊值,老公的妹妹穿的比我還像新娘。我一直安慰自己育灸,他們只是感情好腻窒,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著磅崭,像睡著了一般儿子。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上砸喻,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天柔逼,我揣著相機與錄音,去河邊找鬼割岛。 笑死纵柿,一個胖子當著我的面吹牛递递,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼帚湘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俏拱?” 一聲冷哼從身側(cè)響起埃篓,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疆股,沒想到半個月后费坊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡旬痹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年附井,在試婚紗的時候發(fā)現(xiàn)自己被綠了讨越。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡永毅,死狀恐怖把跨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沼死,我是刑警寧澤着逐,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站意蛀,受9級特大地震影響耸别,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜县钥,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一秀姐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧若贮,春花似錦省有、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至细移,卻和暖如春搏予,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弧轧。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工雪侥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人精绎。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓速缨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親代乃。 傳聞我的和親對象是個殘疾皇子旬牲,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

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

  • gRPC是由Google主導開發(fā)的RPC框架,使用HTTP/2協(xié)議并用ProtoBuf作為序列化工具搁吓。其客戶端提供...
    CZ_Golang閱讀 82,155評論 9 71
  • 1.簡介 在gRPC中原茅,客戶端應用程序可以直接調(diào)用不同計算機上的服務器應用程序上的方法,就像它是本地對象一樣堕仔,使您...
    第八共同體閱讀 1,880評論 0 6
  • Prerequisites(先決條件) GoGo的三個最新主要版本之一 Protocol buffer 編譯器擂橘,p...
    panic閱讀 506評論 0 0
  • gRPC與gochassis 盡管grpc-go本身也自帶一些云原生能力,比如負載均衡摩骨,但是還遠遠不夠通贞,并且需要使...
    田曉亮_7ed1閱讀 1,512評論 0 7
  • 表情是什么朗若,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息昌罩。高興了當然就笑了哭懈,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,138評論 2 7