当前位置: 首页 > 知识库问答 >
问题:

使用Docker Swarm的Spring Boot管理无法提取运行状况度量

鲜于温书
2023-03-14

我正在尝试使用zookeeper发现服务机制让spring boot admin在docker swarm集群中工作,以确保所有客户端在连接到zookeeper后都能被动态发现。问题是,由于连接被拒绝,springboot admin似乎无法到达客户端上的健康执行器endpoint,尽管所有docker服务都使用相同的覆盖网络,并且每个容器都可以ping彼此,我通过docker Exec-it ping验证了这一点,以确保它们都可以从彼此访问。

Ive还验证了客户端和管理服务的正确连接到zookeeper,并且zookeeper+admin dashboard实际上看到这些客户端已经注册。

为了重新创建这个问题,我创建了一个简单的docker compose,通过下面的compose文件,在同一个覆盖网络上部署了两个启用了执行器的Spring Boot管理应用程序:

version: '3.1'

services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

从这个配置中,我看到了在zookeeper中注册的spring管理仪表板,并且显示为脱机(因为它无法到达/health执行器)

以下两个地址是它在SBA中为客户端注册的地址。https://10.255.0.19:8080/OFFLINE https://10.255.0.20:8080/OFFLINE

我得到的例外。

2018-12-31 04:20:31.926  INFO 1 --- [    updateTask1] d.c.boot.admin.registry.StatusUpdater    : Couldn't retrieve status for Application [id=28eab1e1, name=nsp-admin, managementUrl=https://10.255.0.20:8080/, healthUrl=https://10.255.0.20:8080/health, serviceUrl=https://10.255.0.20:8080/]
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://10.255.0.20:8080/health": Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out; nested exception is org.apache.http.conn.ConnectTimeoutException: Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:628) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:549) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at de.codecentric.boot.admin.web.client.ApplicationOperations.doGet(ApplicationOperations.java:68) ~[spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.web.client.ApplicationOperations.getHealth(ApplicationOperations.java:58) ~[spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdater.queryStatus(StatusUpdater.java:111) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdater.updateStatus(StatusUpdater.java:65) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at de.codecentric.boot.admin.registry.StatusUpdateApplicationListener$1.run(StatusUpdateApplicationListener.java:47) [spring-boot-admin-server-1.5.6.jar!/:1.5.6]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_151]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_151]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]
Caused by: org.apache.http.conn.ConnectTimeoutException: Connect to 10.255.0.20:8080 [/10.255.0.20] failed: connect timed out
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652) ~[spring-web-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
        ... 15 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_151]
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_151]
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_151]
        at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_151]
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:339) ~[httpclient-4.5.3.jar!/:4.5.3]
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ~[httpclient-4.5.3.jar!/:4.5.3]

我的SBA配置yml

server:
  port: 8080
spring:
  boot:
    admin:
      client:
        prefer-ip: false
  datasource:
    driverClassName: org.postgresql.Driver
    url: ${DB_URL}
    username: ${DB_USER}
    password: ${DB_PASSWORD}
  application:
    name: nsp-admin
  cloud:
    config:
      discovery:
        enabled: true
    zookeeper:
      connect-string: ${ZK_HOST}
      discovery:
        uri-spec: https://{address}:{port}
        metadata:
          management:
            context-path: /
          health:
            path: /health

management:
  security:
    enabled: false

security:
  basic:
    enabled: false

#security.require-ssl: true
server.ssl.enabled: true
server.ssl.key-store-type: PKCS12
server.ssl.key-store: *****
server.ssl.key-store-password: *****

当我使用docker ID作为主机名执行curl时,/health api在执行从SBA到客户端容器ID的curl时返回。

此操作:docker Exec-IT 8403C5001B9E curl-k https://bf41c73af594:8080/health

这不起作用将导致超时:docker exec-it 8403c5001b9e curl-k https://10.255.0.20:8080/health

是否可以强制zookeeper注册主机名或containerid?

更新设置spring.cloud.zookeeper.discovery.instanceHost:my Application.yml中的${HOSTNAME}解决了这个问题。它强制将正确的containerId注册到Zookeeper。

共有1个答案

杜海
2023-03-14

你不需要做所有这些马戏团。在Docker中,有一个概念叫做服务发现。它是由Docker负责的本地DNS解析。

您可以使用容器名称,也可以指定别名而不是IP/container id,因为这些名称每次都会更改。

默认情况下,docker添加带有服务名称的网络名称来命名容器。您可以通过使用decker-compose中的container_name关键字为容器固定一个名称。则可以使用该名称而不是IP。这将解决相应的容器。

version: '3.1'

services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        container_name: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        container_name: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

compose文件示例:

version: '3.1'
services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            default:
                aliases:
                    - zoo1
                    - zoo.1
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            default:
                aliases:
                    - zoo2
                    - zoo.2
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    default:
      external:
        name: nsp_test

这里的zoo1可以解析为zoo1,zoo1,zoo1.nsp_test,zoo.1.nsp_test。对于zoo2也是如此。也适用于群模式。

如果您知道正在创建的服务的名称,那么您也可以使用它来解析容器。

例如:

version: '3.1'
services:
    zoo1:
        image: zookeeper:3.4.12
        hostname: zoo1
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda5v]
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=0.0.0.0:2888:3888 server.2=zoo2:2888:3888

    zoo2:
        image: zookeeper:3.4.12
        hostname: zoo2
        networks:
            - nsp_test
        deploy:
            restart_policy:
                condition: on-failure
            placement:
                constraints: [node.hostname == nj51nreda6v]
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=0.0.0.0:2888:3888

    nspadmin:
        image: admin:77
        ports:
            - "9084:8080"
        networks:
            - nsp_test
        depends_on:
            - "zoo1"
            - "zoo2"
        deploy:
            restart_policy:
                condition: on-failure
            mode: global
        environment:
            ZK_HOST: zoo1:2181,zoo2:2182
            SPRING_PROFILES_ACTIVE: ssldev
networks:
    nsp_test:
      external:
        name: nsp_test

假设上面的配置创建了名称为zoo1_nsp_testzoo2_nsp_test的容器。您也可以通过使用这些名称来解析容器。不适合群节点,因为容器名称因主机而异。

注意:
只有当容器连接到同一网络时,上述所有方法才起作用。

参考资料:

  1. 撰写文件版本3引用#CONTAINER_NAME
  2. 撰写文件版本3引用#别名
  3. 服务发现
  4. 负载平衡、服务发现和安全性
 类似资料:
  • 在我的spring yaml文件中: 有人知道我做错了什么吗? 谢谢你。

  • 目前,我在为springboot项目获取mysql数据时遇到了一个问题: 编辑:Application.Properties 我能够使/test/welcome映射工作,因此我相信我对服务和控制器的实现是正确的。所以我想知道我是不是在访问存储库中的数据库时犯了一个错误,还是应该使用JpaRepository而不是CrudRepository并使用显式查询? 编辑堆栈跟踪:org.springfra

  • 我正在使用乌班图12.04和日食朱诺。我安装了 ADT 21.0.1 和所有 SDK 包。但是每次我开始日食时,都会有如下错误: 当我尝试运行sdk Manager时,它显示错误: 任何人都可以帮忙吗?

  • 我最近将应用程序中的Spring Boot版本从1.4更新到了1.5.1,我注意到在AWS上部署到弹性Beanstalk后,healtch检查开始失败。 在我们的AWS环境中,所有的通信都是通过HTTPS进行的,包括health(健康),它以前在Spring Boot和Acture1.4中工作得很好,但在Verson1.5中,我们开始在Actures healthendpoint上得到401。 有

  • 我有一个spring boot rest api项目--我无法使spring boot执行器/健康endpoint工作。当我尝试转到localhost:8080/health时,它就会出现一个“白标签错误页面”。我尝试向我的application.properties添加各种属性,但似乎都不起作用--我不需要任何自定义映射或对执行器endpoint的身份验证。下面是我的建筑。格拉德尔-有什么建议吗