How to configure endpoints and esp to publish gRPC with enabled ServerReflection feature

7/20/2018

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
-- Dimaf
google-cloud-endpoints
google-cloud-platform
google-kubernetes-engine

2 Answers

7/23/2018

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
-- Dimaf
Source: StackOverflow

7/23/2018

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

-- Alioua
Source: StackOverflow