如何理解 Spring Boot 应用程序已准备好工作?

Posted

技术标签:

【中文标题】如何理解 Spring Boot 应用程序已准备好工作?【英文标题】:How to understand that spring boot application is ready to work? 【发布时间】:2018-10-24 16:41:10 【问题描述】:

我在春季有几个微服务。其中之一是配置服务器。我尝试使用 docker-compose 完全启动服务。但是有问题。微服务在初始化之前尝试从配置服务器获取配置。我想为微服务的启动编写脚本以防止错误启动。我现在必须如何确定配置服务器准备就绪的时刻。端口监听不起作用。 Docker 隐藏了有关他的网络的信息。我相信有比标准输出解析更好的方法。

有人知道我如何确定 Spring Boot 应用程序的启动时间吗?

【问题讨论】:

你用什么方法监听端口? 如果你使用执行器,你可以检查 /health 端点 【参考方案1】:

有人知道我如何确定 Spring Boot 应用程序的启动时间吗?

当您的应用程序从 /health 端点返回代码 200 并带有类似的有效负载时,它必须准备好


  "status": "UP"

这意味着您的应用程序没有问题并且准备好工作,无论如何,此端点通常由监控应用程序用于了解您的应用程序健康状况,这样它可以维护集群,其他应用程序不常用此端点, 这个显示器一般

使用该端点知道您的应用程序何时准备好接收世界请求,这样它就可以将您的应用程序注册到公共地址,例如 当/health 返回DOWN状态时,尝试重新启动该应用程序以解决问题

看看docker healthcheck,它使用了和spring一样的概念

要使该端点可用,您需要添加弹簧执行器依赖项,这是一个 gradle 示例

compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '1.5.10.RELEASE'

微服务在初始化之前尝试从配置服务器获取配置......

这里有一些要点要明确

Docker compose 不会授予启动顺序,除非您使用 depends_on 子句,无论如何 docker 永远不会等待第一个容器完全启动(使用健康检查的事件)然后启动第二个容器 如果您的微服务 A 依赖于微服务 B 那么 A 必须准备好应对 B 故障和不可用,这是一个微服务的前提,因为它会在某一天或更糟的时候发生,发生在一个不应该发生的意外时刻。 config-server 会在某个时刻重新启动吗?相关应用会发生什么情况?

所以我的建议是让你的应用程序在尝试从 config server 应用程序获取信息时失败,如果失败了你可以做一些事情:

例如重试using spring-retry 如果您可以处理一些临时的配置服务器不可用,那么我的建议是在您的add a custom check /health 中将此信息公开给某些监控微服务 如果您的应用在没有 config server 的情况下无法运行,那么只需调用System.exit(-1) 并让docker-compose restart your application 一遍又一遍,直到 config server 回答一些有用的问题

这里有一些紧凑的例子来模拟你的情况并使用 docker 解决这个问题

配置服务器 app-1

config-server 将比 app-1 花费更长的时间来准备,然后 app-1 将保持不健康 直到 config-server 正确响应

version: '3.4'
services:
  mg-config-server:
    image: nginx:1.10
    healthcheck:
      test: ["CMD", "bash", "-c", "sleep 15; exit 0"]
      interval: 10s
      timeout: 17s
      retries: 3
      start_period: 10s
    networks:
      - my-net
    command: bash -c "echo starting; sleep 20; nginx -g 'daemon off;'"

  mg-app-1:
    image: alpine:3.7
    healthcheck:
      test: ["CMD", "curl", "http://mg-config-server"]
      interval: 5s
      timeout: 5s
      retries: 3
      start_period: 1s
    command: sh -c 'echo starting; apk add --update curl; tail -f /dev/null'
    restart: always
    networks: 
      - my-net
    dns:
    - 8.8.8.8

networks:
  my-net:
    driver: overlay

那就开始吧

docker-compose up
docker ps | grep "mg" 

无论如何,在这种情况下使用 docker swarm 更有意义,因为它会检查运行状况检查端点并在容器不健康时重新启动容器

docker swarm init --advertise-addr <your-machine-ip>
docker stack deploy --compose-file docker-compose.yml my-stack && docker ps | grep "my-stack"

Docker 版本:18.02.0-ce

抱歉回答太长了,希望对你有帮助

【讨论】:

【参考方案2】:

如果您的问题特定于配置服务器, 也可以实现spring重试机制

spring:
   application:
      name: test-service
   cloud:
      config:
         enabled: true
         uri: $CONFIG_SERVER_URL:http://127.0.0.1:8761 #where the config-service is running
         fail-fast: true #the service will not run if it can't reach the config-service
         name: common,test-service
         retry:
           max-attempts: 10
           max-interval: 5000

你还需要有 spring-retry 依赖

// https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
compile group: 'org.springframework.retry', name: 'spring-retry', version: '1.2.4.RELEASE'

【讨论】:

以上是关于如何理解 Spring Boot 应用程序已准备好工作?的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 学习:整合Mybatis

如何在 Spring Boot 应用程序中实现长轮询 REST 端点?

idea中使用spring boot + scala快速开发部署

使用 CAS 保护 Spring Boot Rest 服务

面试官:如何在自定义端口上运行 Spring Boot 应用程序?

http 请求如何在已部署的 Spring Boot 应用程序中工作?