{"id":207351,"date":"2025-07-08T09:55:34","date_gmt":"2025-07-08T01:55:34","guid":{"rendered":"https:\/\/server.hk\/cnblog\/207351\/"},"modified":"2025-07-08T09:55:34","modified_gmt":"2025-07-08T01:55:34","slug":"grpc-%e5%88%b0%e8%bf%9c%e7%a8%8b%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%9a%84%e5%b8%a6%e5%ae%bd%e8%be%83%e6%85%a2","status":"publish","type":"post","link":"https:\/\/server.hk\/cnblog\/207351\/","title":{"rendered":"gRPC \u5230\u8fdc\u7a0b\u670d\u52a1\u5668\u7684\u5e26\u5bbd\u8f83\u6162"},"content":{"rendered":"<p><b><\/b> <\/p>\n<p>\u5f53\u524d\u4f4d\u7f6e\uff1a <span>&gt;<\/span> <span>&gt;<\/span> <span>&gt;<\/span> <span>&gt;<\/span> <span>gRPC \u5230\u8fdc\u7a0b\u670d\u52a1\u5668\u7684\u5e26\u5bbd\u8f83\u6162<\/span><\/p>\n<p><span>\u6765\u6e90\uff1astackoverflow<\/span><br \/>\n<span>2024-04-21 21:36:37<\/span><br \/>\n<span><i><\/i>0\u6d4f\u89c8<\/span><br \/>\n<span style=\"cursor: pointer\"><i><\/i>\u6536\u85cf<\/span> <\/p>\n<p><span style=\"font-size: 15px\">\u5b66\u4e60\u77e5\u8bc6\u8981\u5584\u4e8e\u601d\u8003\uff0c\u601d\u8003\uff0c\u518d\u601d\u8003\uff01\u4eca\u5929\u5c0f\u7f16\u5c31\u7ed9\u5927\u5bb6\u5e26\u6765<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">\u300agRPC \u5230\u8fdc\u7a0b\u670d\u52a1\u5668\u7684\u5e26\u5bbd\u8f83\u6162\u300b<\/span>\uff0c\u4ee5\u4e0b\u5185\u5bb9\u4e3b\u8981\u5305\u542b<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\"><\/span>\u7b49\u77e5\u8bc6\u70b9\uff0c\u5982\u679c\u4f60\u6b63\u5728\u5b66\u4e60\u6216\u51c6\u5907\u5b66\u4e60<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">Golang<\/span>\uff0c\u5c31\u90fd\u4e0d\u8981\u9519\u8fc7\u672c\u6587\u5566~\u8ba9\u6211\u4eec\u4e00\u8d77\u6765\u770b\u770b\u5427\uff0c\u80fd\u5e2e\u52a9\u5230\u4f60\u5c31\u66f4\u597d\u4e86\uff01<\/span><\/p>\n<p> \u95ee\u9898\u5185\u5bb9<br \/>\n <\/p>\n<p>\u6211\u6709\u4e00\u4e2a grpc \u670d\u52a1\uff0c\u53ef\u4ee5\u5c06\u6587\u4ef6\u4ece\u672c\u5730\u8ba1\u7b97\u673a\u4f20\u8f93\u5230\u8fdc\u7a0b\u670d\u52a1\u5668\uff0c\u5e76\u4e14\u6211\u6ce8\u610f\u5230\u4e00\u4e9b\u4e25\u91cd\u7684\u5e26\u5bbd\u95ee\u9898\u3002\u5e73\u5747\u800c\u8a00\uff0c\u5728\u4e00\u4e2a\u8fde\u63a5\u5171\u4eab\u591a\u4e2a\u6d41\uff08\u901a\u5e38\u7ea6\u4e3a 8 \u4e2a\uff09\u7684\u60c5\u51b5\u4e0b\uff0c\u4e0b\u8f7d\u901f\u5ea6\u7ea6\u4e3a 1mb\/s\u3002<\/p>\n<p>\u670d\u52a1\u5668\u4f7f\u7528tls\u8fdb\u884c\u52a0\u5bc6\uff0c\u4f46\u8fd9\u4f3c\u4e4e\u4e0d\u662f\u74f6\u9888\uff0c\u56e0\u4e3a\u5173\u95edtls\u5bf9\u6027\u80fd\u7684\u5f71\u54cd\u53ef\u4ee5\u5ffd\u7565\u4e0d\u8ba1\u3002\u6211\u8fd8\u5c1d\u8bd5\u4f7f\u7528 <code>iperf3<\/code> \u76f4\u63a5\u6d4b\u8bd5\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u4e4b\u95f4\u7684\u5e26\u5bbd\uff0c\u7ed3\u679c\u4e3a 10mb\/s\u3002<\/p>\n<pre>connecting to host &lt;host&gt;, port &lt;port&gt;\n[  7] local 10.0.0.112 port 59651 connected to &lt;ip&gt; port &lt;port&gt;\n[ id] interval           transfer     bitrate\n[  7]   0.00-1.00   sec  1.28 mbytes  10.7 mbits\/sec\n[  7]   1.00-2.00   sec   894 kbytes  7.35 mbits\/sec\n[  7]   2.00-3.00   sec   999 kbytes  8.17 mbits\/sec\n[  7]   3.00-4.00   sec  1.19 mbytes  10.0 mbits\/sec\n[  7]   4.00-5.00   sec   753 kbytes  6.17 mbits\/sec\n[  7]   5.00-6.00   sec  1.16 mbytes  9.67 mbits\/sec\n[  7]   6.00-7.00   sec  1.00 mbytes  8.44 mbits\/sec\n[  7]   7.00-8.00   sec  1.26 mbytes  10.5 mbits\/sec\n[  7]   8.00-9.00   sec  1.22 mbytes  10.2 mbits\/sec\n[  7]   9.00-10.00  sec  1.15 mbytes  9.66 mbits\/sec\n- - - - - - - - - - - - - - - - - - - - - - - - -\n[ id] interval           transfer     bitrate\n[  7]   0.00-10.00  sec  10.8 mbytes  9.09 mbits\/sec                  sender\n[  7]   0.00-10.00  sec  10.7 mbytes  8.95 mbits\/sec                  receiver<\/pre>\n<p>\u5ba2\u6237\u7aef\u4e0a\u4f20\u5e26\u5bbd\u7ea610mb\/s\uff0c\u670d\u52a1\u5668\u4e0b\u8f7d\u7ea650mb\/s\uff08\u901a\u8fc7<code>speedtest-cli<\/code>\uff09<\/p>\n<p><code>traceroute<\/code> \u4e5f\u6ca1\u6709\u663e\u793a\u4efb\u4f55\u6709\u8da3\u7684\u5185\u5bb9&#8230;<\/p>\n<pre>traceroute to mikemeredith.ddns.net (108.52.111.249), 64 hops max, 72 byte packets\n 1  10.0.0.1 (10.0.0.1)  2.195 ms  5.388 ms  1.385 ms\n 2  &lt;ip&gt;  (&lt;ip&gt;)  8.256 ms  145.115 ms  19.025 ms\n 3  &lt;ip2&gt; (&lt;ip2&gt;)  9.951 ms  9.471 ms  141.929 ms\n 4  &lt;ip3&gt; (&lt;ip3&gt;)  18.389 ms  9.684 ms  12.248 ms\n 5  &lt;ip4&gt; (&lt;ip4&gt;)  143.880 ms  25.077 ms  10.606 ms\n 6  ae-13-ar01.capitolhghts.md.bad.comcast.net (68.87.168.61)  142.567 ms  137.153 ms  20.790 ms\n 7  be-33657-cr02.ashburn.va.ibone.comcast.net (68.86.90.57)  14.326 ms  144.076 ms  22.957 ms\n 8  be-1102-cs01.ashburn.va.ibone.comcast.net (96.110.32.169)  13.881 ms  144.756 ms  23.981 ms\n 9  be-2107-pe07.ashburn.va.ibone.comcast.net (96.110.32.186)  20.203 ms  94.433 ms  23.034 ms\n10  n-a.gw12.iad8.alter.net (152.179.50.205)  20.254 ms  278.023 ms  31.660 ms\n11  * * *\n12  &lt;ip12&gt; (&lt;ip13&gt;)  66.277 ms  39.229 ms  34.543 ms\n13  &lt;ip13&gt; (&lt;ip14&gt;)  48.849 ms  49.300 ms  49.546 ms<\/pre>\n<p> \u8fd9\u662f\u5b9e\u9645\u7684\u4ee3\u7801<\/p>\n<p>\u5ba2\u6237\u7aef\u8fde\u63a5\uff1a<\/p>\n<pre>creds, err := credentials.newclienttlsfromfile(cerloc, \"\")\nif err != nil {\n    fmt..printf(\"failed to get tls from file: %v\\n\", err)\n    panic(err)\n}\nconn, err = grpc.dial(host+port, grpc.withtransportcredentials(creds))\n<\/pre>\n<p>\u5ba2\u6237\u7aef\u6d41\uff1a<\/p>\n<pre>ctx, cancel := context.withcancel(context.background())\ndefer cancel()\nclient := proto.client(conn)\nstream, err := client.backupfiles(ctx, grpc.usecompressor(gzip.name))\n\/\/ send on stream, max size of message is 2mb\n<\/pre>\n<p>\u670d\u52a1\u5668\u76d1\u542c\uff1a<\/p>\n<pre>\/\/ Start serving on port\nl, err := net.Listen(\"tcp\", port)\nif err != nil {\n    fmt.Printf(\"error listening on port %v: %v\\n\", port, err)\n    panic(err)\n}\n\nvar s *grpc.Server\ncreds, err := credentials.NewServerTLSFromFile(\n    certLoc,\n    keyLoc,\n)\nif err != nil {\n    fmt.Printf(\"error getting tls certs: %v\\n\", err)\n    panic(err)\n}\ns = grpc.NewServer(grpc.Creds(creds))\nproto.RegisterBackupServer(s, &amp;server{})\nerr = s.Serve(l)\n\n\n\/\/ Actual stream handling\n\n\/\/ Get a pooled SharedBuffer for assembling the file\nb := getBuffer()\ndefer putBuffer(b)\nc := make(chan int, []50)\nu, _ := user.Current()\n\nuid := uuid.New()\nfout, err := os.Create(filePath + uid.String())\nif err != nil {\n    fmt.Println(\"error creating staging file: \", err)\n    panic(err)\n}\nvar wg sync.WaitGroup\n\ngo assemble(b, fout, c, &amp;wg)\nfor {\n    in, err := stream.Recv()\n    if err == io.EOF {\n        break\n    }\n    if err != nil {\n        fmt.Println(\"encountered an error receiving on stream: \", err)\n        return err\n    }\n\n\n    bytesWritten = b.LockWrite(in.Payload) \/\/ This buffer is shared between the stream and the go routine\n\n    c &lt;- bytesWritten\n}\n\n\nclose(c)\nwg.Wait()\n\n_ = fout.Close()\n\n\/\/ This is a pre-declared workerpool that basically moves files around \nwp.Submit(func() {\n    finalizeFile(fout.Name(), name, perms, \"\", checkSum, userID)\n})\n\nreturn stream.SendAndClose(&amp;proto.Resp{\n    Status:   true,\n})\n\nfunc assemble(b *buffer.SharedBuffer, fout *os.File, in chan int, wg *sync.WaitGroup) {\n    wg.Add(1)\n    defer wg.Done()\n\n    buf := make([]byte, buffer.BUFFSIZE*2)\n\n    for i := range in {\n        if fout != nil {\n            b.Lock()\n            _, err := b.Read(buf[:i])\n            b.Unlock()\n            if err == io.EOF {\n                continue\n            }\n            if err != nil {\n                panic(err)\n            }\n            n, err := fout.Write(buf[:i])\n            if err != nil {\n                panic(err)\n            }\n            if n != i {\n                fmt.Printf(\"failed to write all bytes to file: %v != %v\", n, i)\n                panic(err)\n            }\n        }\n    }\n}\n<\/pre>\n<p>\u4f3c\u4e4e\u6211\u53ef\u80fd\u9057\u6f0f\u4e86 grpc \u5185\u90e8\u5de5\u4f5c\u539f\u7406\u7684\u4e00\u4e9b\u4e1c\u897f\uff1f<\/p>\n<p> <\/p>\n<h2>\u89e3\u51b3\u65b9\u6848<\/h2>\n<p> <\/p>\n<p>\u5982\u679c\u6211\u6ca1\u731c\u9519\u7684\u8bdd\uff0c\u60a8\u6b63\u5728\u8bfb\u53d6\u4e00\u4e2a goroutine \u4e2d\u7684\u8f93\u5165\u6d41\u5e76\u5c06\u5b57\u8282\u5206\u6d3e\u5230\u7b2c\u4e8c\u4e2a goroutine\u3002\u4e3a\u4ec0\u4e48\u4e0d\u8ba9\u7b2c\u4e8c\u4e2a goroutine \u5b8c\u5168\u5904\u7406\u6d41\u5462\uff1f\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\uff0c\u7b2c\u4e00\u4e2a goroutine \u53ef\u4ee5\u81ea\u7531\u5730\u5904\u7406\u540e\u7eed\u6d41\uff08\u5982\u679c\u6709\uff09\u3002 <\/p>\n<p>\u901a\u5e38\u7684\u6a21\u5f0f\u662f\u8ba9\u4e00\u4e2a goroutine \u76d1\u542c\u4f20\u5165\u7684\u8bf7\u6c42\u5e76\u751f\u6210\u65b0\u7684 goroutine \u6765\u5904\u7406\u5b83\u4eec\u3002\u81f3\u5173\u91cd\u8981\u7684\u662f\uff0c\u9664\u4e86\u76d1\u542c\u8bf7\u6c42\u7684 api \u4e4b\u5916\uff0c\u4e3b goroutine \u4e0d\u8c03\u7528\u4efb\u4f55\u963b\u585e api\u3002<\/p>\n<p>\u4f8b\u5982\uff1a<\/p>\n<pre>for {\n    newStream := ListenForStreams() \/\/Block until next stream\n    go consumeStream(newStream)\n}<\/pre>\n<p>\u4eca\u5929\u5e26\u5927\u5bb6\u4e86\u89e3\u4e86\u7684\u76f8\u5173\u77e5\u8bc6\uff0c\u5e0c\u671b\u5bf9\u4f60\u6709\u6240\u5e2e\u52a9\uff1b\u5173\u4e8eGolang\u7684\u6280\u672f\u77e5\u8bc6\u6211\u4eec\u4f1a\u4e00\u70b9\u70b9\u6df1\u5165\u4ecb\u7ecd\uff0c\u6b22\u8fce\u5927\u5bb6\u5173\u6ce8\u516c\u4f17\u53f7\uff0c\u4e00\u8d77\u5b66\u4e60\u7f16\u7a0b~<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5f53\u524d\u4f4d\u7f6e\uff1a &gt; &gt; &#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4925],"tags":[],"class_list":["post-207351","post","type-post","status-publish","format-standard","hentry","category-4925"],"_links":{"self":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/207351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/comments?post=207351"}],"version-history":[{"count":0,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/207351\/revisions"}],"wp:attachment":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/media?parent=207351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/categories?post=207351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/tags?post=207351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}