【问题标题】:Spring Boot REST app returns 400 when requested from other docker-compose service by service nameSpring Boot REST 应用程序在通过服务名称从其他 docker-compose 服务请求时返回 400
【发布时间】:2019-01-08 23:50:48
【问题描述】:

我正在尝试在我们的开发设置中引入 Spring Boot REST 服务。开发设置使用 docker-compose 和 API 网关在同一域(即 localhost)上公开各个服务。

当我尝试通过共享 docker-compose 文件中的服务名称从另一个容器内部向我的服务发出 HTTP 请求时,服务返回 400。

设置

我已经编辑了我们的 docker-compose 文件,所以它看起来像下面介绍 Spring Boot Java 服务。该服务基于 spring-boot-starter-parent (2.0.3.RELEASE) 和 spring-boot-starter-web。我没有配置任何与 Web 服务器相关的东西(除了添加 server.server-header 属性以确保我自己的请求正在访问我的服务)。

version: '3'
services:
  ...

  hello_java:
    build:
      context: ../hello-java/
      dockerfile: Dockerfile
    depends_on:
      - postgres
      - castle_black
    ports:
      - "8301:8080"

  castle_black:
    build: ../castle-black/tyk-gateway
    ports:
      - "8191:8080"
    depends_on:
      - redis

行为

如果我从容器外部请求 hello 服务(例如在 localhost:8301 上的浏览​​器中),它会正确回复。如果我在一个容器中,但获取了带有我的新服务的容器在 docker 网络中获取的 IP,并使用该新服务也正确响应。

下面我展示了从 API 网关容器内部到 Java 服务的请求,首先使用服务名称,然后使用解析的 IP。它只在 IP 情况下回复正确的响应。

# curl -v http://hello_java:8080/hello-java/greet?username=Java
* Hostname was NOT found in DNS cache
*   Trying 172.19.0.6...
* Connected to hello_java (172.19.0.6) port 8080 (#0)
> GET /hello-java/greet?username=Java HTTP/1.1
> User-Agent: curl/7.35.0
> Host: hello_java:8080
> Accept: */*
> 
< HTTP/1.1 400 
< Transfer-Encoding: chunked
< Date: Wed, 01 Aug 2018 11:34:34 GMT
< Connection: close
* Server MySpringBootApp is not blacklisted
< Server: MySpringBootApp
< 
* Closing connection 0

# curl -v http://172.19.0.6:8080/hello-java/greet?username=Java
* Hostname was NOT found in DNS cache
*   Trying 172.19.0.6...
* Connected to 172.19.0.6 (172.19.0.6) port 8080 (#0)
> GET /hello-java/greet?username=Java HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 172.19.0.6:8080
> Accept: */*
> 
< HTTP/1.1 200 
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 10
< Date: Wed, 01 Aug 2018 11:34:55 GMT
* Server MySpringBootApp is not blacklisted
< Server: MySpringBootApp
< 
* Connection #0 to host 172.19.0.6 left intact
Hello Java

问题

当客户端添加“Host: hello_java:8080”标头时,标准 spring-boot-starter-web 设置中是否存在阻止 Web 服务器为请求提供服务的内容?或者为什么 Web 服务器在这两种情况下表现不同?我该怎么办?

【问题讨论】:

  • 您提到了 API 网关(Zuul、Spring Cloud Gateway,...?) - 您的网关本身是服务(以及 docker 容器的一部分)吗?如果不是,则网关(外部)和服务(容器内部)具有不同的“localhost”,并且网关无法设置代理。
  • API 网关是 tyk.io,它在 compose 文件的第二个容器中运行。当我只是在 API 网关容器中运行 bash 时,我可以访问 hello_java 容器中的 Web 服务器。如果我向 hello_java 发出 HTTP 请求,Web 服务器将返回 400 状态代码,而如果我向 hello_java 在容器中解析到的 IP 发出请求,它会给出正确的响应(200 OK)。

标签: java spring-boot docker-compose bad-request


【解决方案1】:

经过一些实验,结果证明是服务名称中的下划线导致了问题。将服务名称更改为不包含下划线即可解决问题。

【讨论】:

  • 这个。经过无数小时的调试后,此处提供的解决方案也对我有所帮助。虽然我的服务名称中仍然包含一个下划线,并且我的 nginx 反向代理在向它们路由请求时没有问题,但当我引入包含两个下划线的服务时,它会拒绝这样做。我现在完全重命名了有问题的服务(只是一个词),事情开始起作用了。所以感谢 OP 与我们分享这个!
  • 我从未对找到解决方案如此生气。非常感谢你发布这个,我从来没有猜到这是问题
【解决方案2】:

RFC 952 规定“名称”(网络、主机、网关或域名)是从字母 (AZ)、数字 (0-9)、减号 (-)、和句号 (.)

似乎 _ 不是主机名的有效组件。这有点令人困惑,因为我遇到了同样的问题,当我 ping app_server 时它很好,但是当我从 app_server 获取时,我收到了错误的请求。

将下划线更改为减号已为我解决了问题。

【讨论】:

  • 很抱歉,您的说法不正确。 RFC952 已被其他 RFC 更新(例如,允许将数字作为第一个符号),并未过时。我没有时间从“更新者”关系的传递闭包中遍历所有 RFC,但我认为对主机名使用下划线的限制仍然有效。如果没有,请指出放宽限制的适当 RFC。无论如何,从名称中删除下划线为我解决了问题。
猜你喜欢
  • 2017-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 2020-10-07
相关资源
最近更新 更多