I created a simple gRPC API service, published it using GKE-ESP-endpoints. It works. Now I would like to publish the service with ServerReflection
feature. Reflection has been added into the gRPC server and when some grpc client, for instance grpcurl
, directly sends list
request to the server, the server returns the correct answer with the list of accessible gRPC services:
$ grpcurl --plaintext localhost:8000 list
grservices.diagnostic
When the same request is sent to public ip of load-balancer the answer is Failed to list services: rpc error: code = NotFound desc = Method does not exist.
Logs of esp:
"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0" 404 0 "-" "grpc-go/1.14.0-dev"
Logs of endpoints:
Endpoints management skipped for an unrecognized HTTP call: POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo
For me it looks the reason is in because endpoints
don't know about grpc.reflection.v1alpha.ServerReflection
service and don't allow routing the request to gRPC container. I reviewed all examples that I can googled and didn't see any changes between api-config.yaml
files for gRPC with enabled ServerReflection
and without ServerReflection
.
I have tried to change api_config.yaml
and apply it for the deployment with no success unfortunately, because I should have descriptor {{.pb}} file for {{grpc.reflection.v1alpha.ServerReflection}}.
So my question is how to configure endpoints and esp to provide reflection
?
Thanks a lot for any ideas and proposals.
api_config.yaml:
type: google.api.Service
config_version: 3
#
# Name of the service configuration.
#
name: diagnostic.endpoints.[id-project].cloud.goog
#
# API title to appear in the user interface (Google Cloud Console).
#
title: diagnostic gRPC API
apis:
- name: grservices.diagnostic
# -name: grpc.reflection.v1alpha.ServerReflection
#
# API usage restrictions.
#
#usage:
# rules:
# # Diagnostic methods can be called without an API Key.
# - selector: grservices.diagnostic.GetDateTime
# allow_unregistered_calls: true
#
# - selector: grservices.diagnostic.GetTimeZones
# allow_unregistered_calls: true
#
## - selector: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo
## allow_unregistered_calls: true
usage:
rules:
# Allow unregistered calls for all methods.
- selector: "*"
allow_unregistered_calls: true
The solution is quite simple. I just downloaded reflection.proto
and compiled the new .pb
file using reflection.proto
and my own proto
file of my services:
wget https://raw.githubusercontent.com/grpc/grpc/master/src/proto/grpc/reflection/v1alpha/reflection.proto
python -m grpc.tools.protoc --include_imports --include_source_info --proto_path=. --proto_path="../googleapis" --python_out=. --grpc_python_out=. --descriptor_set_out=api_descriptor.pb reflection.proto diagnostic.proto
# delete _pb2.py files of reflection. The files are already presented in virtenv as the part of grpcio-reflection package
rm reflection_pb2.py
rm reflection_pb2_gprc.py
# upload the new config to endpoints
gcloud endpoints services deploy api_descriptor.pb api_config.yaml
Testing:
$ grpcurl -insecure ${EXT_IP}:443 list
grservices.diagnostic
$ grpcurl -insecure ${EXT_IP}:443 list grservices.diagnostic
GetDateTime
GetTimeZones
grpcurl -insecure ${EXT_IP}:443 grservices.diagnostic.GetDateTime
{
"datetime": "2018-07-23 17:21:16"
}
$ grpcurl -insecure ${EXT_IP}:443 grservices.diagnostic/GetdateTime
$ grpcurl -d '{"time_zone": "Israel"}' -insecure ${EXT_IP}:443 grservices.diagnostic.GetDateTime
{
"datetime": "2018-07-23 20:25:41Z+0300"
}
The changed part of api_config.yaml
file:
apis:
- name: grservices.diagnostic
- name: grpc.reflection.v1alpha.ServerReflection
The browser expects the HTTP response to contain valid CORS headers. But The backend is gRPC, it could not handle CORS.
You can find your solution Here