问题
I have a basic, proof-of-concept Python gRPC server.
When I run my docker container locally, I can make requests to the server and receive responses on the exposed port.
I can successfully deploy the server to Cloud Run, and I see the service running in the Cloud Run UI.
However, I am unable to access the Cloud Run version from a client.
I am looking for suggestions to help me access this server, whether it is changes to the clients or the server.
Client code:
with grpc.insecure_channel('...-uc.a.run.app:80') as channel:
stub = tax_service_pb2_grpc.TaxServiceStub(channel)
response = stub.GetTaxRate(tax_service_pb2.GetTaxRateRequest(zipcode='12345'))
print("Tax client received: {}".format(response.tax_rate))
If I try to connect to port 80, I received this message:
raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "Trying to connect an http1.x server"
debug_error_string = "{"created":"@1575613033.176590200","description":"Error received from peer ipv4:216.239.36.53:80","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Trying to connect an http1.x server","grpc_status":14}"
If I try to connect to port 443, I receive
raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "Trying to connect an http1.x server"
debug_error_string = "{"created":"@1575613033.176590200","description":"Error received from peer ipv4:216.239.36.53:80","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Trying to connect an http1.x server","grpc_status":14}"
Server code:
import time
from concurrent import futures
import grpc
from grpc_reflection.v1alpha import reflection
import tax_service_pb2
import tax_service_pb2_grpc
class TaxServicer(tax_service_pb2_grpc.TaxServiceServicer):
def GetTaxRate(self, request, context):
return tax_service_pb2.GetTaxRateResponse(tax_rate=1.5)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
tax_service_pb2_grpc.add_TaxServiceServicer_to_server(TaxServicer(), server)
SERVICE_NAMES = (
tax_service_pb2.DESCRIPTOR.services_by_name['TaxService'].full_name,
reflection.SERVICE_NAME,
)
reflection.enable_server_reflection(SERVICE_NAMES, server)
server.add_insecure_port('0.0.0.0:{}'.format(os.environ.get('PORT', 8080)))
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
logging.basicConfig()
serve()
回答1:
No changes were needed on the server side.
The insecure port is used by Cloud Run to access the gRPC service, and then the SSL is added between the edge of Google's cloud and clients.
On my client, I needed to use the system root certificate in order to access the service
with grpc.secure_channel('<app-url>-uc.a.run.app:443', grpc.ssl_channel_credentials()) as channel:
stub = tax_service_pb2_grpc.TaxServiceStub(channel)
response = stub.GetTaxRate(tax_service_pb2.GetTaxRateRequest(zipcode='12345'))
print("Tax client received: {}".format(response.tax_rate))
回答2:
I think that your problem is you try to create an insecure channel on a SSL enpoint. I used this part of code to create my client channel:
with open('certificate.pem', 'rb') as f:
creds = grpc.ssl_channel_credentials(f.read())
channel = grpc.secure_channel('predict-<PROJECTHASH>-uc.a.run.app:443',creds)
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
...
You can download the certificate from your web browser.
回答3:
Are you running your server in the $PORT
provided by Cloud Run? Maybe try setting a simple endpoint that just returns a 200 and see if you can hit that and get a response back?
来源:https://stackoverflow.com/questions/59207914/run-a-python-grpc-server-on-google-cloud-run