使用 GRPC 与 Google Cloud Run 通信的 Google App Engine 给出“错误:14 不可用:连接已断开”

Posted

技术标签:

【中文标题】使用 GRPC 与 Google Cloud Run 通信的 Google App Engine 给出“错误:14 不可用:连接已断开”【英文标题】:Google App Engine communicating with Google Cloud Run using GRPC gives "Error: 14 UNAVAILABLE: Connection dropped" 【发布时间】:2022-01-11 16:27:06 【问题描述】:

tl;博士

在镜像中用 C++ 编写的 gRPC 服务器(本地 Docker,在线云运行)在本地工作,但当用 node.js 编写的 gRPC 客户端向它发送请求时,它不能在线工作。无论客户端是本地还是 Google App 引擎上的客户端都是如此。该图像绝对有效,因为当 grpcurl 向其发送请求时它会正确响应。

详细信息

Node.js 中的客户端代码

import loadPackageDefinition, credentials from '@grpc/grpc-js';
import loadSync from '@grpc/proto-loader';

const packageDef = loadSync(
    './path/to/file.proto',
    keepCase: true,
      longs: String,
      enums: String,
      defaults: true,
      oneofs: true,
    ,
);
const packageNameProto = loadPackageDefinition(packageDef).packageName;
const client = new packageProto.ServiceName(
      `$host:$port`,
      credentials.createInsecure(),
);
client.calculation(tempInputs, function(err, result) 
    // code
);

C++ 中的服务器代码。

void RunServer()

    int port = 50051;
    char* port_ptr = std::getenv("PORT");
    if (port_ptr != nullptr) 
        port = std::atoi(port_ptr);
    
    if (port < MIN_PORT or MAX_PORT < port) 
        port = 50051;
    
    std::ostringstream server_address;
    server_address << "0.0.0.0:" << port;
    // std::string server_address("0.0.0.0:50051");
    ServiceNameServiceImpl service;

    grpc::EnableDefaultHealthCheckService(true);
    grpc::reflection::InitProtoReflectionServerBuilderPlugin();
    ServerBuilder builder;
    // Listen on the given address without any authentication mechanism.
    builder.AddListeningPort(server_address.str(), grpc::InsecureServerCredentials());
    // Register "service" as the instance through which we'll communicate with
    // clients. In this case it corresponds to an *synchronous* service.
    builder.RegisterService(&service);
    // Finally assemble the server.
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address.str() << std::endl;

    // Wait for the server to shutdown. Note that some other thread must be
    // responsible for shutting down the server for this call to ever return.
    server->Wait();


int main(int argc, char** argv)

    RunServer();
    return 0;

客户端和服务器、GCP和本地兼容性表

Local Server on Docker in WSL2 Cloud Run Server
Local Client from command line in Ubuntu on WSL2 Works using localhost:50051 and 'my-external-ip address':50051 port forwarded to my machine Doesn't work using 'cloud-run-url':443, giving the "Error: 14 UNAVAILABLE: Connection dropped"
App Engine Client Works using 'my-external-ip address':50051 port forwarded to my machine Doesn't work using 'cloud-run-url':443, giving the "Error: 14 UNAVAILABLE: Connection dropped"
grpcurl command in Ubuntu on WSL2 X Works using 'cloud-run-url':443 as cloud run wants requests on 443. Command is 'docker run -i -v pwd:/protos fullstorydev/grpcurl -d @ -proto protos/file.proto cloud.run.url.run.app:443 protoPackage.ProtoService.proto_function < inputs.json'

根据 Google 文档,服务器映像为 built 和 deployed。

客户端使用gcloud app deploy部署。

在云运行服务触发器中,我将“入口”设置为“允许所有流量”,将“身份验证”设置为“允许未经身份验证的调用”。

HTTP/2 连接已启用。我也尝试过禁用它们,因为'Using gRPC' 指南说你只需要在使用 gRPC 流时进行设置,而我没有。

错误日志:(已删除私人信息)


  "textPayload": "Error: 14 UNAVAILABLE: Connection dropped\n    at Object.callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:26)\n    at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:180:52)\n    at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:336:141)\n    at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:299:181)\n    at /workspace/node_modules/@grpc/grpc-js/build/src/call-stream.js:160:78\n    at processTicksAndRejections (internal/process/task_queues.js:77:11) ",
  "insertId": "61adfe9d000b03a0c#######",
  "resource": 
    "type": "gae_app",
    "labels": 
      "project_id": "$PROJECT_ID",
      "module_id": "default",
      "zone": "europe-west2-3",
      "version_id": "20211206t121319"
    
  ,
  "timestamp": "2021-12-06T12:14:21.721824Z",
  "severity": "ERROR",
  "labels": 
    "clone_id": "00c61b117ca5f61b7b4b7b7dde5eddded10f5bead78cf0cf0eee3fe1111a982786d972c65976ff49ddd14eaab4b708ed52349b06cc1538deacc7a89b8d6641b55a14f5799#######"
  ,
  "logName": "projects/$PROJECT_ID/logs/stdout",
  "receiveTimestamp": "2021-12-06T12:14:22.008561030Z"

带有“GRPC_TRACE=all GRPC_VERBOSITY=DEBUG”的错误日志:(已删除私人信息)

D 2021-12-06T12:25:38.616Z | resolving_load_balancer | dns:$CLOUD_RUN_URL:443 CONNECTING -> CONNECTING
D 2021-12-06T12:25:38.616Z | channel | (22) dns:$CLOUD_RUN_URL:443 callRefTimer.unref | configSelectionQueue.length=0 pickQueue.length=0
D 2021-12-06T12:25:38.616Z | channel | (22) dns:$CLOUD_RUN_URL:443 Pick result: QUEUE subchannel: undefined status: undefined undefined
D 2021-12-06T12:25:38.616Z | channel | (22) dns:$CLOUD_RUN_URL:443 callRefTimer.ref | configSelectionQueue.length=0 pickQueue.length=1
D 2021-12-06T12:25:38.616Z | connectivity_state | (22) dns:$CLOUD_RUN_URL:443 CONNECTING -> CONNECTING
D 2021-12-06T12:25:38.617Z | subchannel | (24) $CLOUD_RUN_IP_ADD_1:443 CONNECTING -> READY
D 2021-12-06T12:25:38.618Z | pick_first | Pick subchannel with address $CLOUD_RUN_IP_ADD_1:443
D 2021-12-06T12:25:38.618Z | pick_first | CONNECTING -> READY
D 2021-12-06T12:25:38.618Z | resolving_load_balancer | dns:$CLOUD_RUN_URL:443 CONNECTING -> READY
D 2021-12-06T12:25:38.618Z | channel | (22) dns:$CLOUD_RUN_URL:443 callRefTimer.unref | configSelectionQueue.length=0 pickQueue.length=0
D 2021-12-06T12:25:38.618Z | channel | (22) dns:$CLOUD_RUN_URL:443 Pick result: COMPLETE subchannel: $CLOUD_RUN_IP_ADD_1:443 status: undefined undefined
D 2021-12-06T12:25:38.618Z | connectivity_state | (22) dns:$CLOUD_RUN_URL:443 CONNECTING -> READY
D 2021-12-06T12:25:38.618Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 refcount 2 -> 3
D 2021-12-06T12:25:38.618Z | subchannel_refcount | (23) $CLOUD_RUN_IPV6_1::a:443 refcount 3 -> 2
D 2021-12-06T12:25:38.618Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (25) $CLOUD_RUN_IPV6_2::a:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (26) $CLOUD_RUN_IP_ADD_2:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (27) $CLOUD_RUN_IPV6_3::a:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (28) $CLOUD_RUN_IP_ADD_3:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (29) $CLOUD_RUN_IPV6_4::a:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (30) $CLOUD_RUN_IP_ADD_4:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (31) $CLOUD_RUN_IPV6_3::35:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (32) $CLOUD_RUN_IP_ADD_5:443 refcount 3 -> 2
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (23) $CLOUD_RUN_IPV6_1::a:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (26) $CLOUD_RUN_IP_ADD_2:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (25) $CLOUD_RUN_IPV6_2::a:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (28) $CLOUD_RUN_IP_ADD_3:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (27) $CLOUD_RUN_IPV6_3::a:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (30) $CLOUD_RUN_IP_ADD_4:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (29) $CLOUD_RUN_IPV6_4::a:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | subchannel_refcount | (32) $CLOUD_RUN_IP_ADD_5:443 refcount 2 -> 1
D 2021-12-06T12:25:38.619Z | call_stream | Starting stream on subchannel (24) $CLOUD_RUN_IP_ADD_1:443 with headers
                grpc-accept-encoding: identity,deflate,gzip
                accept-encoding: identity
                :authority: $CLOUD_RUN_URL:443
                user-agent: grpc-node-js/1.4.4
                content-type: application/grpc
                :method: POST
                :path: /protoPackage.ProtoService/proto_function
                te: trailers

D 2021-12-06T12:25:38.620Z | call_stream | [3] attachHttp2Stream from subchannel $CLOUD_RUN_IP_ADD_1:443
D 2021-12-06T12:25:38.620Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 callRefcount 0 -> 1
D 2021-12-06T12:25:38.620Z | call_stream | [3] sending data chunk of length 223 (deferred)
D 2021-12-06T12:25:38.620Z | call_stream | [3] calling end() on HTTP/2 stream
D 2021-12-06T12:25:38.627Z | call_stream | [3] ended with status: code=14 details="Connection dropped"
D 2021-12-06T12:25:38.628Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 callRefcount 1 -> 0
D 2021-12-06T12:25:38.628Z | call_stream | [3] close http2 stream with code 8
ERROR!
Error: 14 UNAVAILABLE: Connection dropped
    at Object.callErrorFromStatus (/home/sam/nodejs/elevate-online-njs/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/home/sam/nodejs/elevate-online-njs/node_modules/@grpc/grpc-js/build/src/client.js:180:52)
    at Object.onReceiveStatus (/home/sam/nodejs/elevate-online-njs/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:336:141)
    at Object.onReceiveStatus (/home/sam/nodejs/elevate-online-njs/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:299:181)
    at /home/sam/nodejs/elevate-online-njs/node_modules/@grpc/grpc-js/build/src/call-stream.js:160:78
    at processTicksAndRejections (internal/process/task_queues.js:77:11) 
  code: 14,
  details: 'Connection dropped',
  metadata: Metadata  internalRepr: Map(0) , options:  

D 2021-12-06T12:25:38.631Z | subchannel | (24) $CLOUD_RUN_IP_ADD_1:443 connection closed
D 2021-12-06T12:25:38.632Z | subchannel | (24) $CLOUD_RUN_IP_ADD_1:443 READY -> IDLE
D 2021-12-06T12:25:38.632Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 refcount 2 -> 1
D 2021-12-06T12:25:38.632Z | pick_first | READY -> IDLE
D 2021-12-06T12:25:38.632Z | resolving_load_balancer | dns:$CLOUD_RUN_URL:443 READY -> IDLE
D 2021-12-06T12:25:38.632Z | connectivity_state | (22) dns:$CLOUD_RUN_URL:443 READY -> IDLE
D 2021-12-06T12:25:38.632Z | call_stream | [3] HTTP/2 stream closed with code 8
D 2021-12-06T12:25:39.275Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.275Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.277Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_1::a:443 - Local (:::0)
D 2021-12-06T12:25:39.277Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 connection closed
D 2021-12-06T12:25:39.277Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.278Z | subchannel | (2) $CLOUD_RUN_IPV6_1::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.278Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.279Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.280Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_2::a:443 - Local (:::0)
D 2021-12-06T12:25:39.281Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 connection closed
D 2021-12-06T12:25:39.281Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.281Z | subchannel | (4) $CLOUD_RUN_IPV6_2::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.281Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.282Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.284Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_3::a:443 - Local (:::0)
D 2021-12-06T12:25:39.284Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 connection closed
D 2021-12-06T12:25:39.284Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.284Z | subchannel | (6) $CLOUD_RUN_IPV6_3::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.284Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.285Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.286Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_4::a:443 - Local (:::0)
D 2021-12-06T12:25:39.287Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 connection closed
D 2021-12-06T12:25:39.288Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.289Z | subchannel | (8) $CLOUD_RUN_IPV6_4::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.290Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.291Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.293Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_5::200a:443 - Local (:::0)
D 2021-12-06T12:25:39.293Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 connection closed
D 2021-12-06T12:25:39.294Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.294Z | subchannel | (10) $CLOUD_RUN_IPV6_5::200a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.602Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.602Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.604Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_1::a:443 - Local (:::0)
D 2021-12-06T12:25:39.604Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 connection closed
D 2021-12-06T12:25:39.604Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.605Z | subchannel | (23) $CLOUD_RUN_IPV6_1::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.605Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.606Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.607Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_2::a:443 - Local (:::0)
D 2021-12-06T12:25:39.607Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 connection closed
D 2021-12-06T12:25:39.607Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.608Z | subchannel | (25) $CLOUD_RUN_IPV6_2::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.608Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.608Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.610Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_3::a:443 - Local (:::0)
D 2021-12-06T12:25:39.610Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 connection closed
D 2021-12-06T12:25:39.610Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.611Z | subchannel | (27) $CLOUD_RUN_IPV6_3::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.611Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.611Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 creating HTTP/2 session
D 2021-12-06T12:25:39.612Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_4::a:443 - Local (:::0)
D 2021-12-06T12:25:39.612Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 connection closed
D 2021-12-06T12:25:39.612Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.612Z | subchannel | (29) $CLOUD_RUN_IPV6_4::a:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:39.613Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 TRANSIENT_FAILURE -> CONNECTING
D 2021-12-06T12:25:39.613Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 creating HTTP/2 session
D 2021-12-06T12:25:39.614Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 connection closed with error connect ENETUNREACH $CLOUD_RUN_IPV6_3::35:443 - Local (:::0)
D 2021-12-06T12:25:39.614Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 connection closed
D 2021-12-06T12:25:39.614Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:39.614Z | subchannel | (31) $CLOUD_RUN_IPV6_3::35:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.270Z | subchannel_refcount | (2) $CLOUD_RUN_IPV6_1::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.270Z | subchannel_refcount | (4) $CLOUD_RUN_IPV6_2::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.270Z | subchannel_refcount | (5) $CLOUD_RUN_IP_ADD_2:443 refcount 1 -> 0
D 2021-12-06T12:25:48.271Z | subchannel | (5) $CLOUD_RUN_IP_ADD_2:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.271Z | subchannel_refcount | (6) $CLOUD_RUN_IPV6_3::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.271Z | subchannel_refcount | (7) $CLOUD_RUN_IP_ADD_3:443 refcount 1 -> 0
D 2021-12-06T12:25:48.271Z | subchannel | (7) $CLOUD_RUN_IP_ADD_3:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.271Z | subchannel_refcount | (8) $CLOUD_RUN_IPV6_4::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.271Z | subchannel_refcount | (9) $CLOUD_RUN_IP_ADD_4:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel | (9) $CLOUD_RUN_IP_ADD_4:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (10) $CLOUD_RUN_IPV6_5::200a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (11) $CLOUD_RUN_IP_ADD_5:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel | (11) $CLOUD_RUN_IP_ADD_5:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (23) $CLOUD_RUN_IPV6_1::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (24) $CLOUD_RUN_IP_ADD_1:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (25) $CLOUD_RUN_IPV6_2::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel_refcount | (26) $CLOUD_RUN_IP_ADD_2:443 refcount 1 -> 0
D 2021-12-06T12:25:48.272Z | subchannel | (26) $CLOUD_RUN_IP_ADD_2:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (27) $CLOUD_RUN_IPV6_3::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (28) $CLOUD_RUN_IP_ADD_3:443 refcount 1 -> 0
D 2021-12-06T12:25:48.273Z | subchannel | (28) $CLOUD_RUN_IP_ADD_3:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (29) $CLOUD_RUN_IPV6_4::a:443 refcount 1 -> 0
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (30) $CLOUD_RUN_IP_ADD_4:443 refcount 1 -> 0
D 2021-12-06T12:25:48.273Z | subchannel | (30) $CLOUD_RUN_IP_ADD_4:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (31) $CLOUD_RUN_IPV6_3::35:443 refcount 1 -> 0
D 2021-12-06T12:25:48.273Z | subchannel_refcount | (32) $CLOUD_RUN_IP_ADD_5:443 refcount 1 -> 0
D 2021-12-06T12:25:48.274Z | subchannel | (32) $CLOUD_RUN_IP_ADD_5:443 CONNECTING -> TRANSIENT_FAILURE
D 2021-12-06T12:25:48.274Z | subchannel | (5) $CLOUD_RUN_IP_ADD_2:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.274Z | subchannel | (7) $CLOUD_RUN_IP_ADD_3:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.274Z | subchannel | (9) $CLOUD_RUN_IP_ADD_4:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.274Z | subchannel | (11) $CLOUD_RUN_IP_ADD_5:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.274Z | subchannel | (26) $CLOUD_RUN_IP_ADD_2:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.275Z | subchannel | (28) $CLOUD_RUN_IP_ADD_3:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.275Z | subchannel | (30) $CLOUD_RUN_IP_ADD_4:443 TRANSIENT_FAILURE -> IDLE
D 2021-12-06T12:25:48.275Z | subchannel | (32) $CLOUD_RUN_IP_ADD_5:443 TRANSIENT_FAILURE -> IDLE

【问题讨论】:

【参考方案1】:

从grpc documentation 开始,credentials.createSsl() 的所有 3 个参数都是可选的。然而,

如果使用客户端证书,则必须同时传递第二个和第三个参数。

因此,因为我使用的是客户端证书并且没有传递 private_key 或 cert_chain,所以我不得不禁用“NODE_TLS_REJECT_UNAUTHORIZED”。

因此,文档表明只使用credentials.createSsl() 而不传递证书是可以的。但是official code examples 并未将其作为示例用例。

我目前的工作代码是


import loadPackageDefinition, credentials from '@grpc/grpc-js';
import loadSync from '@grpc/proto-loader';

const packageDef = loadSync(
    './path/to/file.proto',
    keepCase: true,
      longs: String,
      enums: String,
      defaults: true,
      oneofs: true,
    ,
);
const packageNameProto = loadPackageDefinition(packageDef).packageName;
const ssl_creds = credentials.createSsl();
const client = new packageNameProto.Uppeak(
    `$host:$port`,
    ssl_creds,
);

感谢 Pablo 指出这一点。

旧答案

我们现在有一个解决方案来让它工作,但这绝对不是一个理想的解决方案。

我们不使用grpc.credentials.createInsecure(),而是按照guide(底部概述的步骤)创建自签名SSL证书。

然后在 node.js 代码中如下使用它。请注意,将NODE_TLS_REJECT_UNAUTHORIZED 设置为“0”会引发警告。

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // new

import loadPackageDefinition, credentials from '@grpc/grpc-js';
import loadSync from '@grpc/proto-loader';
import readFileSync from 'fs'; // new

const packageDef = loadSync(
    './path/to/file.proto',
    keepCase: true,
      longs: String,
      enums: String,
      defaults: true,
      oneofs: true,
    ,
);
const packageNameProto = loadPackageDefinition(packageDef).packageName;

const root_cert = readFileSync('./server.crt'); // new
const ssl_creds = credentials.createSsl(root_cert); // new

const client = new packageNameProto.Uppeak(
    `$host:$port`,
    ssl_creds,
); // changed

Creating a self signed certificate

    您需要在 Linux 上安装 Apache 和 openssl。 生成服务器密钥: openssl genrsa -des3 -out server.key 4096 用它创建一个证书签名请求。此命令将提示一系列内容(国家、州或省等)。确保“通用名称(例如,您的姓名)”与您的盒子注册的完全限定域名(或您的 IP 地址,如果您没有的话)匹配: openssl req -new -key server.key -out server.csr 现在对证书签名请求进行签名。此示例持续 365 天: openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

【讨论】:

这很好,但也阅读您的问题,我认为您可能发现了一个错误。我在 [Issue Tracker](issuetracker.google.com) 上看不到任何报告,我设法找到的只是github issue where someone with your problem latched on,但在说他们会这样做之后并没有创建自己的问题,只是说那"logging is helping shed more light on the problem"。关于使用443...The docs you shared只指定需要使用port env,我觉得可以改一下? 在我的情况下,使用grpc.credentials.createSsl() 就足够了,无需任何自行生成的根证书。 @Pablo 我自己试一试,然后更新答案

以上是关于使用 GRPC 与 Google Cloud Run 通信的 Google App Engine 给出“错误:14 不可用:连接已断开”的主要内容,如果未能解决你的问题,请参考以下文章

使用 grpc 和 protobuf(生成的客户端)通过 HTTP 2 访问 Google Cloud Pubsub

如何在 Google Cloud Platform 上部署 GRPC 服务器和客户端?

Spring Cloud集成grpc

pip install google-cloud-pubsub 在 docker 容器中安装失败

是否可以从 Google Cloud 服务请求跟踪?

PubSubException:io.grpc.StatusRuntimeException:不可用