设置 gRPC DB-less API 网关:415 Unsupported Media Type

Posted

技术标签:

【中文标题】设置 gRPC DB-less API 网关:415 Unsupported Media Type【英文标题】:Setup gRPC DB-less API gateway: 415 Unsupported Media Type 【发布时间】:2020-07-10 11:09:59 【问题描述】:

我是我项目的当前设置 kong。原来,服务器是单体架构),我的团队想把它分成微服务。作为我使用 gRPC 在客户端和服务器之间进行通信的项目,我正在考虑使用支持 gRPC 的 API 网关。我在 Google 和 Medium 中找到了 Kong 的建议。并且我已将其设置为无 DB 模式。我使用 docker-compose 运行。以下是我所做的:

这里是 docker-compose.yml

version: '3'
networks:
    kong-net:
        driver: bridge
services:
    gateway:
        image: kong:2.0.2
        networks:
            - kong-net
        volumes:
            - ./../kong:/var/lib/docker/volumes/kong-vol/_data
        environment:
            KONG_SSL:                       "off"
            KONG_DATABASE:                  "off"
            KONG_DECLARATIVE_CONFIG:        /var/lib/docker/volumes/kong-vol/_data/kong.yml
            #KONG_SSL_CERT:                  /
            #KONG_SSL_CERT_KEY:              /
            KONG_PROXY_LISTEN:              0.0.0.0:8000, 0.0.0.0:8443 ssl, 0.0.0.0:9080 http2, 0.0.0.0:9081 http2 ssl
            KONG_ADMIN_LISTEN:              127.0.0.1:8001, 127.0.0.1:8444 ssl
        ports:
            - "8000:8000"
            - "8443:8443"
            - "8001:8001"
            - "8444:8444"
            - "9080:9080"
            - "9081:9081"
        healthcheck:
            test: ["CMD", "kong", "health"]
            interval: 5s
            timeout: 2s
            retries: 15
        restart: on-failure
    appserver:
        image: saigonparkingmap/appserver:v1.0
        networks:
            - kong-net
        ports:
            - "9090:9090"
            - "9999:9999"
        depends_on:
            - gateway

这里是kong.yml

services:
    -   name: appserver
        url: http://localhost:8001/services
        protocol: grpc
        host: appserser
        port: 9999
        connect_timeout: 30000
        write_timeout: 30000
        read_timeout: 30000
        routes:
            -   name: parking-lot-service
                protocols:
                    - grpc
                paths:
                    - /com.bht.parkingmap.api.proto.parkinglot.ParkingLotService/

我遇到了来自 Kong 的 415 Unsupported Media Type Error 响应。

这是我从客户端控制台收到的信息:

Caused by: io.grpc.StatusRuntimeException: UNKNOWN: HTTP status code 415
invalid content-type: text/html; charset=UTF-8
headers: Metadata(:status=415,content-type=text/html; charset=UTF-8,content-length=144,date=Sun, 29 Mar 2020 23:24:57 GMT,access-control-allow-origin=*,server=kong/2.0.2,x-kong-admin-latency=381,x-kong-upstream-latency=381,x-kong-proxy-latency=2,via=kong/2.0.2)
DATA-----------------------------
<html>
<head><title>415 Unsupported Media Type</title></head>
<body>
<center><h1>415 Unsupported Media Type</h1></center>
</body>
</html>

    at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:240)
    at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:221)
    at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:140)
    at com.bht.parkingmap.api.proto.parkinglot.ParkingLotServiceGrpc$ParkingLotServiceBlockingStub.getParkingLotById

这是我从 Kong Docker Container 收到的内容:

gateway_1    | 2020/03/29 23:24:56 [warn] 23#0: *490 a client request body is buffered to a temporary file /usr/local/kong/client_body_temp/0000000001, client: 172.20.0.1, server: kong, request: "POST /com.bht.parkingmap.api.proto.parkinglot.ParkingLotService/getParkingLotById HTTP/2.0", host: "localhost:9080"
gateway_1    | 127.0.0.1 - - [29/Mar/2020:23:24:57 +0000] "POST /services/com.bht.parkingmap.api.proto.parkinglot.ParkingLotService/getParkingLotById HTTP/1.1" 415 144 "-" "grpc-java-netty/1.27.2"
gateway_1    | 172.20.0.1 - - [29/Mar/2020:23:24:57 +0000] "POST /com.bht.parkingmap.api.proto.parkinglot.ParkingLotService/getParkingLotById HTTP/2.0" 415 144 "-" "grpc-java-netty/1.27.2"

我从客户端调用到 Kong 网关端口 9080 使用 ManagedChannel 的存根,并期待它将来服务服务器侦听端口 9999。

客户端(存根)----> Kong :9080 ----> Service :9999

我是否遗漏了配置中的某些内容,或者我误解了有关 grpc 网关的任何内容? 我期待得到您的支持!非常感谢。

【问题讨论】:

也有同样的经历。关注这篇文章。 【参考方案1】:

您的kong.yml 有问题。 Kong 服务中的 url 键是 protocol://host:port 属性的简写。

我通过在我的kong.yml 中执行此操作来实现它:

_format_version: "1.1"

services:
  - name: grpc
    protocol: grpc
    host: host.docker.internal
    port: 9797
    routes:
      - name: catch-all-grpc-requests
        paths:
          - /
        protocols:
          - grpc

这与使用 url 简写的等效。这将产生与上述相同的效果:

_format_version: "1.1"

services:
  - name: grpc
    url: grpc://host.docker.internal:9797
    routes:
      - name: catch-all-grpc-requests
        paths:
          - /
        protocols:
          - grpc

这是假设我的 gRPC 服务器在我的 localhost 的端口 9797 上运行。

我使用了host.docker.internal,以便我的 Kong Docker 容器可以访问我也暴露于 :9797 的 Dockerized gRPC 服务器。

然后我grpcurl希望这样:

grpcurl -v -d '"name": "Ken"' -plaintext localhost:9080 facade.GreetingService/SayHello

所以发生的事情是:

客户端 (grpcurl) -> Kong HTTP2 代理侦听器 (:9080) -> gRPC 服务器 (:9797)

来源:https://konghq.com/blog/manage-grpc-services-kong/

【讨论】:

以上是关于设置 gRPC DB-less API 网关:415 Unsupported Media Type的主要内容,如果未能解决你的问题,请参考以下文章

用于 gRpc 服务的 API 网关

ETCD:HTTP JSON API通过gRPC网关

API 网关 gRPC-Gateway V2 初探

云原生 API 网关,gRPC-Gateway V2 初探

使用 Spring Boot 的 gRPC 和 REST 微服务

23.创建grpc网关的基本设置和运行方法