{"id":3623,"date":"2021-08-15T17:03:00","date_gmt":"2021-08-15T09:03:00","guid":{"rendered":"https:\/\/wyxxt.org.cn\/?p=3623"},"modified":"2024-07-03T22:01:51","modified_gmt":"2024-07-03T14:01:51","slug":"protobuf%e4%b8%8egrpc","status":"publish","type":"post","link":"https:\/\/wyxxt.org.cn\/?p=3623","title":{"rendered":"protobuf\u4e0egrpc"},"content":{"rendered":"<h1>protobuf<\/h1>\n<h2>\u6982\u5ff5<\/h2>\n<p>protobuf\u662f Google \u7684\u8bed\u8a00\u4e2d\u7acb\u3001\u5e73\u53f0\u4e2d\u7acb\u3001\u53ef\u6269\u5c55\u7684\u7ed3\u6784\u5316\u6570\u636e<strong>\u5e8f\u5217\u5316<\/strong>\u673a\u5236\u2014\u2014\u60f3\u60f3 XML\uff0c\u4f46\u66f4\u5c0f\u3001\u66f4\u5feb\u3001\u66f4\u7b80\u5355\u3002\u60a8\u53ef\u4ee5\u5b9a\u4e49\u4e00\u6b21\u6570\u636e\u7684\u7ed3\u6784\u5316\u65b9\u5f0f\uff0c\u7136\u540e\u60a8\u53ef\u4ee5\u4f7f\u7528\u7279\u6b8a\u751f\u6210\u7684\u6e90\u4ee3\u7801\u8f7b\u677e\u5730\u4f7f\u7528\u5404\u79cd\u8bed\u8a00\u5728\u5404\u79cd\u6570\u636e\u6d41\u4e2d\u5199\u5165\u548c\u8bfb\u53d6\u7ed3\u6784\u5316\u6570\u636e\u3002<\/p>\n<p>protobuf\u76ee\u524d\u652f\u6301\u5728 Java\u3001Python\u3001Objective-C \u548c C++ \u4e2d\u751f\u6210\u7684\u4ee3\u7801\u3002\u4f7f\u7528\u6211\u4eec\u65b0\u7684 proto3 \u8bed\u8a00\u7248\u672c\uff0c\u60a8\u8fd8\u53ef\u4ee5\u4f7f\u7528 Dart\u3001Go\u3001Ruby \u548c C#\uff0c\u4ee5\u53ca\u66f4\u591a\u7684\u8bed\u8a00\u3002<a href=\"https:\/\/protobuf.dev\/\">\u5b98\u7f51<\/a><\/p>\n<h2>\u8de8\u8bed\u8a00\u7684\u5e8f\u5217\u5316\u65b9\u6848<\/h2>\n<p>\u8de8\u8bed\u8a00\u5e8f\u5217\u5316\u65b9\u6848\u6709\uff1a protobuf, thrift, json\uff0cxml<\/p>\n<p><a href=\"https:\/\/tech.meituan.com\/2015\/02\/26\/serialization-vs-deserialization.html\">\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316-\u7f8e\u56e2<\/a><\/p>\n<p>Protobuf\u662f\u4e00\u4e2a\u7eaf\u7cb9\u7684\u5e94\u7528\u5c42\u534f\u8bae\uff0c\u53ef\u4ee5\u548c\u5404\u79cd\u4f20\u8f93\u5c42\u534f\u8bae\u4e00\u8d77\u4f7f\u7528<\/p>\n<h2>\u5b9a\u4e49\u534f\u8bae\u683c\u5f0f<\/h2>\n<pre><code class=\"language-shell\">go get github.com\/golang\/protobuf\/protoc-gen-go\ngo get github.com\/golang\/protobuf\/proto<\/code><\/pre>\n<p>Address book.proto<\/p>\n<pre><code class=\"language-protobuf\">syntax = \"proto3\";\npackage tutorial;\n\nimport \"google\/protobuf\/timestamp.proto\";\n\noption go_package = \"..\/tutorial\";\n\nmessage Person {\n  string name = 1;\n  int32 id =2;\n  string email = 3;\n\n  enum PhoneType {\n    MOBILE = 0;\n    HOME = 1;\n    WORK = 2;\n  }\n\n  message PhoneNumber {\n    string number = 1;\n    PhoneType type = 2;\n  }\n\n  repeated PhoneNumber phones = 4;\n\n  google.protobuf.Timestamp last_updated = 5;\n}\n\nmessage AddressBook {\n  repeated Person people = 1;\n}<\/code><\/pre>\n<h2>\u7f16\u8bd1protocol buffers<\/h2>\n<pre><code class=\"language-shell\">protoc --go_out=. *proto<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_af5d1f208353b320feecfb8439d107fd.jpg\" alt=\"\" \/><\/p>\n<p>\u81ea\u52a8\u751f\u6210\u5982\u4e0b\u4ee3\u7801<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_22150330fd3a859446f77ce1e91ba461.jpg\" alt=\"\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_131838e778f965682b024fb0e3434890.jpg\" alt=\"\" \/><\/p>\n<h2>\u4f7f\u7528\u793a\u4f8b<\/h2>\n<pre><code class=\"language-shell\">go get google.golang.org\/protobuf\/reflect\/protoreflect\ngo get google.golang.org\/protobuf\/runtime\/protoimpl<\/code><\/pre>\n<p>server.go<\/p>\n<pre><code class=\"language-go\">\/**\n * Createby GoLand\n * User xzw jsjxzw@163.com\n * Date 2021\/8\/1\n * Time \u4e0b\u53484:38\n *\/\n\npackage main\n\nimport (\n    \"github.com\/gin-gonic\/gin\"\n    \"imooc.com\/ccmouse\/learngo\/grpc\/tutorial\"\n    \"net\/http\"\n)\n\nfunc main() {\n    r := gin.Default()\n    r.GET(\"\/protobuf\", func(c *gin.Context) {\n        p :=  &tutorial.Person{\n            Name:        \"xzw\",\n            Id:          1,\n            Email:       \"jsjxzw@163.com\",\n            Phones: []*tutorial.Person_PhoneNumber{\n                {\n                    Number:\"15012345678\",\n                    Type:tutorial.Person_MOBILE,\n                },\n            },\n        }\n        c.ProtoBuf(http.StatusOK, p)\n    })\n    r.Run(\":8080\")\n}\n<\/code><\/pre>\n<p>client.go<\/p>\n<pre><code class=\"language-go\">\/**\n * Createby GoLand\n * User xzw jsjxzw@163.com\n * Date 2021\/8\/1\n * Time \u4e0b\u53484:56\n *\/\n\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com\/golang\/protobuf\/proto\"\n    \"imooc.com\/ccmouse\/learngo\/grpc\/tutorial\"\n    \"io\/ioutil\"\n    \"net\/http\"\n    \"reflect\"\n)\n\nfunc main() {\n    resp,err := http.Get(\"http:\/\/localhost:8080\/protobuf\")\n    if err != nil {\n        fmt.Println(err)\n        return\n    }\n    defer resp.Body.Close()\n    body,err := ioutil.ReadAll(resp.Body)\n    if err!= nil {\n        fmt.Println(err)\n        return\n    }\n    p := &tutorial.Person{}\n    proto.Unmarshal(body, p)\n    fmt.Println(*p)\n    fmt.Println(reflect.TypeOf(*p))\n}<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_e9f07a9ebe8e6839297ca9dea2356706.jpg\" alt=\"\" \/><\/p>\n<h1>gRPC<\/h1>\n<h2>\u6982\u5ff5<\/h2>\n<p>gRPC \u662f\u4e00\u79cd\u73b0\u4ee3\u5f00\u6e90\u9ad8\u6027\u80fd\u8fdc\u7a0b\u8fc7\u7a0b\u8c03\u7528 (RPC) \u6846\u67b6\uff0c\u53ef\u4ee5\u5728\u4efb\u4f55\u73af\u5883\u4e2d\u8fd0\u884c\u3002\u5b83\u53ef\u4ee5\u901a\u8fc7\u5bf9\u8d1f\u8f7d\u5e73\u8861\u3001\u8ddf\u8e2a\u3001\u5065\u5eb7\u68c0\u67e5\u548c\u8eab\u4efd\u9a8c\u8bc1\u7684\u53ef\u63d2\u62d4\u652f\u6301\uff0c\u6709\u6548\u5730\u8fde\u63a5\u6570\u636e\u4e2d\u5fc3\u5185\u548c\u6570\u636e\u4e2d\u5fc3\u4e4b\u95f4\u7684\u670d\u52a1\u3002\u5b83\u8fd8\u9002\u7528\u4e8e\u5206\u5e03\u5f0f\u8ba1\u7b97\u7684\u6700\u540e\u4e00\u82f1\u91cc\uff0c\u5c06\u8bbe\u5907\u3001\u79fb\u52a8\u5e94\u7528\u7a0b\u5e8f\u548c\u6d4f\u89c8\u5668\u8fde\u63a5\u5230\u540e\u7aef\u670d\u52a1\u3002<a href=\"https:\/\/www.grpc.io\/\">\u5b98\u7f51<\/a><\/p>\n<h2>\u5b9a\u4e49\u534f\u8bae\u683c\u5f0f<\/h2>\n<pre><code class=\"language-shell\">go get google.golang.org\/protobuf\/cmd\/protoc-gen-go@v1.27\ngo get google.golang.org\/grpc\/cmd\/protoc-gen-go-grpc@v1.1<\/code><\/pre>\n<p>\u5728\u539f\u57fa\u7840\u4e0a\u6dfb\u52a0<\/p>\n<pre><code class=\"language-protobuf\">\/\/ gRPC\nservice Greeter {\n  rpc GetPerson (PersonId) returns (Person) {}\n}\n\nmessage PersonId {\n  int32 id = 1;\n}<\/code><\/pre>\n<h2>\u7f16\u8bd1protocol buffers<\/h2>\n<pre><code class=\"language-shell\">protoc --go-grpc_out=. *.proto# \u540c\u65f6\u751f\u6210 http \u548c grpc \u5e8f\u5217\u5316\u7c7bprotoc --go_out=. --go-grpc_out=. *.proto<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_2a5aa8fa5006f99323d1ffdbf15cb951.jpg\" alt=\"\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_e7145f0b91f453750b8ad0bbd0c9cad1.jpg\" alt=\"\" \/><\/p>\n<h2>\u4f7f\u7528\u793a\u4f8b<\/h2>\n<pre><code class=\"language-shell\">go get google.golang.org\/grpc<\/code><\/pre>\n<p>server.go<\/p>\n<pre><code class=\"language-go\">\/** * Createby GoLand * User xzw jsjxzw@163.com * Date 2021\/8\/1 * Time \u4e0b\u53485:36 *\/package mainimport (    \"context\"   \"google.golang.org\/grpc\"    \"imooc.com\/ccmouse\/learngo\/grpc\/tutorial\"   \"log\"   \"net\")type server struct {  tutorial.UnimplementedGreeterServer}func (s *server) GetPerson(ctx context.Context, in *tutorial.PersonId) (*tutorial.Person, error) {  log.Printf(\"Received: %v\", in.GetId())  return &tutorial.Person{            Name:        \"\",            Id:          in.GetId(),            Email:       \"\",            Phones:      nil,           LastUpdated: nil,       },      nil}func main() {   lis, err := net.Listen(\"tcp\", \":8000\")  if err != nil {     log.Fatalf(\"failed to listen:%v\", err)  }   s := grpc.NewServer()   tutorial.RegisterGreeterServer(s, &server{})    log.Printf(\"server listening as %v\", lis.Addr())    go func() {     if err := ser.Serve(lis); err != nil {          log.Fatalf(\"failed to server:%v\", err)      }   }()  c := make(chan os.Signal, 1)   signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)  for {       s := <-c        switch s {      case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:          \/\/ \u81ea\u52a8\u4f18\u96c5\u505c\u6b62\uff0ctcp\u907f\u514d\u5360\u7528\u8d44\u6e90         ser.GracefulStop()          return      }   }}<\/code><\/pre>\n<p>client.go<\/p>\n<pre><code class=\"language-go\">\/** * Createby GoLand * User xzw jsjxzw@163.com * Date 2021\/8\/1 * Time \u4e0b\u53485:47 *\/package mainimport (    \"context\"   \"google.golang.org\/grpc\"    \"imooc.com\/ccmouse\/learngo\/grpc\/tutorial\"   \"log\"   \"os\"    \"strconv\"   \"time\")const (  address = \"localhost:8000\"  defaultId = 123)func main() {   conn,err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())   if err != nil {     log.Fatalf(\"did not connect: %v\", err)  }   defer conn.Close()  c := tutorial.NewGreeterClient(conn)    var id int32 = defaultId    if len(os.Args) > 1  {      x, err := strconv.ParseInt(os.Args[1], 10, 32)      if err != nil {         log.Fatalf(\"param illgal: %v\", err)     }       id = int32(x)   }   ctx, cancel := context.WithTimeout(context.Background(), time.Second)   defer cancel()  r, err := c.GetPerson(ctx, &tutorial.PersonId{Id:id})   if err != nil {     log.Fatalf(\"could not greet: %v\", err)  }   log.Printf(\"Greeting: %d\", r.GetId())}<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_c76c543a0a8ec97b0d4931253010fc9d.jpg\" alt=\"\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/oss.wyxxt.org.cn\/images\/2021\/09\/18\/wp_editor_md_b82a812c8bb7aa8da2b0b616305fd23b.jpg\" alt=\"\" \/><\/p>\n<p>client_http.go<\/p>\n<pre><code class=\"language-go\">\/**\n    * Createby GoLand\n    * User xzw jsjxzw@163.com\n    * Date 2021\/8\/1\n    * Time \u4e0b\u53487:11\n    *\/\npackage main\n\nimport (\n    \"context\"\n    \"github.com\/gin-gonic\/gin\"\n    \"google.golang.org\/grpc\"\n    \"imooc.com\/ccmouse\/learngo\/grpc\/tutorial\"\n    \"log\"\n    \"net\/http\"\n    \"time\"\n)\n\ntype Server struct {\n    engine *gin.Engine\n    webClient tutorial.GreeterClient\n\n}\n\nfunc InitWebServer (addr string) tutorial.GreeterClient {\n    ctx, cancel := context.WithTimeout(context.Background(), time.Second)\n    defer cancel()\n    conn,err := grpc.DialContext(ctx, addr, []grpc.DialOption{grpc.WithInsecure(),        grpc.WithBlock(),   }...)\n    if err != nil {\n        log.Fatalf(\"did not connect: %v\", err)\n    }\n    client := tutorial.NewGreeterClient(conn)\n    return client\n}\n\nfunc (s *Server) CallWeb(txt *gin.Context) {\n    var in *tutorial.PersonId\n    if err := txt.ShouldBind(&in); err != nil {     \n        log.Fatalf(err.Error()) \n    }   \n    out, err := s.webClient.GetPerson(context.Background(), in) \n    if err != nil {    \n        log.Fatalf(\"could not greet: %v\", err) \n    }   \n    txt.JSON(http.StatusOK, out)\n}\n\nfunc NewHttp(httpAddr string, rpcAddr string) {\n    r := gin.Default()  \n    s := Server{       \n        engine: r,     \n        webClient: InitWebServer(rpcAddr),\n    }   \n    s.engine.GET(\"\/hello\", s.CallWeb)  \n    r.Run(httpAddr)\n}\n\nfunc main() { \n    NewHttp(\":8080\", \":8000\")\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>protobuf \u6982\u5ff5 protobuf\u662f Google \u7684\u8bed\u8a00\u4e2d\u7acb\u3001\u5e73\u53f0\u4e2d\u7acb\u3001\u53ef\u6269\u5c55\u7684\u7ed3\u6784\u5316\u6570\u636e\u5e8f\u5217\u5316\u673a\u5236\u2014 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[15],"tags":[396],"class_list":["post-3623","post","type-post","status-publish","format-standard","hentry","category-15","tag-396"],"_links":{"self":[{"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/posts\/3623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3623"}],"version-history":[{"count":3,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/posts\/3623\/revisions"}],"predecessor-version":[{"id":3948,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=\/wp\/v2\/posts\/3623\/revisions\/3948"}],"wp:attachment":[{"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wyxxt.org.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}