掌握SpringBoot-2.3的容器探针:深入篇

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 深入了解SpringBoot-2.3发布的容器探针技术。掌握更多知识点

欢迎访问我的GitHub

  • 地址:https://github.com/zq2599/blog_demos
  • 内容:原创文章分类汇总,及配套源码,涉及Java、Docker、K8S、DevOPS等

    关于《SpringBoot-2.3容器化技术》系列

  • 《SpringBoot-2.3容器化技术》系列,旨在和大家一起学习实践2.3版本带来的最新容器化技术,让咱们的Java应用更加适应容器化环境,在云计算时代依旧紧跟主流,保持竞争力;
  • 全系列文章分为主题和辅助两部分,主题部分如下:
  1. 《体验SpringBoot(2.3)应用制作Docker镜像(官方方案)》
  2. 《详解SpringBoot(2.3)应用制作Docker镜像(官方方案)》
  3. 《掌握SpringBoot-2.3的容器探针:基础篇》
  4. 《掌握SpringBoot-2.3的容器探针:深入篇》
  5. 《掌握SpringBoot-2.3的容器探针:实战篇》
  • 辅助部分是一些参考资料和备忘总结,如下:
  1. 《SpringBoot-2.3镜像方案为什么要做多个layer》
  2. 《设置非root账号不用sudo直接执行docker命令》
  3. 《开发阶段,将SpringBoot应用快速部署到K8S》

    前文回顾

  4. 本文是《掌握SpringBoot-2.3的容器探针》系列的第二篇,前文 《掌握SpringBoot-2.3的容器探针:基础篇》知道了kubernetes的存活和就绪探针,以及SpringBoot-2.3的actuator新增的两个endpoint,当我们把应用部署到kubernetes环境时,这些知识让我们能配置出官方推荐的探针方案,如下图:
    在这里插入图片描述
  5. 尽管上述配置已经可以覆盖多数场景,依然有三个问题未解决:
  • 首先,SpringBoot为kubernetes提供了两个actuator项,但是那些并未部署在kubernetes的SringBoot应用呢?用不上这两项也要对外暴露这两个服务地址吗?

  • 其次,就绪探针是什么时候开始返回200返回码的?应用启动阶段,业务服务可能需要一段时间才能正常工作,就绪探针要是提前返回了200,那k8s就认为容器可以正常工作了,这时候把外部请求调度过来是无法正常响应的,所以搞清楚就绪探针的状态变化逻辑很重要;

  • 最后,也是最重要的一点:有的场景下,例如外部依赖服务异常、本地全局异常等情况下,业务不想对外提供服务,等到问题解决后业务又可以对外提供服务了,如果此时我们能自己写代码控制就绪探针的返回码,那就做到了控制kubernetes是否将外部请求调度到此容器上,这可是个很实用的功能!

本篇就是为了解决上述问题而作,这些问题解决后才能用好探针技术,让它在容器环境带来更大价值;

关键知识点

解决上述问题的关键集中在以下几个知识点:

  1. SpringBoot对容器环境的判断;
  2. SpringBoot对状态定义;
  3. 获取状态;
  4. 监听状态;
  5. 修改状态;

接下来挨个学习这些知识点;

SpringBoot对容器环境的判断

  1. 官方文档如下图所示,SpringBoot判断是否是kubernetes环境的逻辑很简单:是否有_SERVICE_HOST_SERVICE_PORT这两个环境变量:
    在这里插入图片描述
  2. 熟悉kubernetes的读者看到_SERVICE_HOST"_SERVICE_PORT,应该会想起KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT,这是k8s给pod中配置的环境变量,看来SpringBoot也是针对k8s的这个规则来判定是否是容器环境的(如果将来k8s的某个版本不给pod设置这个环境变量,那些原本可以正常运行的pod岂不是有危险了?);
  3. 接下来通过实践来验证上述规则是否有效;
  4. 创建一个SpringBoot-2.3.0.RELEASE的应用,其pom.xml中的parent信息如下:

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.0.RELEASE</version>
    <relativePath/>
    </parent>
    
  5. 增加actuator依赖:

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  6. 启动该应用,浏览器访问:http://localhost:8080/actuator/health/liveness,返回404错误:
    在这里插入图片描述

  7. 以上返回是符合预期的,因为此时并非在kubernetes环境,接下来将"_SERVICE_HOST_SERVICE_PORT这两个环境变量加入应用进程,看看是否有变化;
  8. 如下图,编辑启动类的配置信息:
    在这里插入图片描述
  9. 点击下图红框位置,即可进入编辑环境变量的窗口:
    在这里插入图片描述
  10. 新的窗口中,操作如下图红框中所示,新增了两个环境变量:
    在这里插入图片描述
  11. 再次运行程序,这次返回的状态码是200:
    在这里插入图片描述
  12. 至此,我们弄明白了SpringBoot是否开启探针的逻辑,即应用是否运行在容器环境,而是否是容器环境的判定逻辑则是_SERVICE_HOST_SERVICE_PORT这两个环境变量是否存在;

    非kubernetes环境开启探针

    /actuator/health/liveness/actuator/health/readiness在kubernetes环境才会开启,但是一般情况下,在开发阶段SpringBoot应用可能运行在自己的电脑上,此时如果想查看这两个接口的返回值有两种方式:

第一种,就是前面提到的添加_SERVICE_HOST_SERVICE_PORT这两个环境变量,让SpringBoot以为当前环境是kubernetes环境;

第二种,是按照官方指导添加属性,如下图红框所示:
在这里插入图片描述

SpringBoot对探针相关状态定义

  1. 首先要弄清楚有哪些状态,源码是最准确的;
  2. 如下图,存活探针一共有两种状态:CORRECT表示应用运行中并且内部状态正常,BROKEN表示应用运行中并且内部是BROKEN状态(请原谅我的英语水平)
    在这里插入图片描述
  3. 如下图,就绪探针一共有两种状态:ACCEPTING_TRAFFIC表示应用可以对外提供服务,REFUSING_TRAFFIC表示应用无法对外提供服务;
    在这里插入图片描述
  4. 另外,上图的since注解显示这两个枚举是从2.3.0版本开始生效的;
  5. 小小八卦一下,上述两个枚举的作者Brian Clozel,坐标法国里昂,目前在sringboot的提交次数排第8名:
    在这里插入图片描述
  6. 在SpringBoot启动过程中,应用、存活探针、就绪探针三者状态对应关系如下图:
    在这里插入图片描述
  7. 在SpringBoot停止过程中,应用、存活探针、就绪探针三者状态对应关系如下图:
    在这里插入图片描述

    获取状态

    如果业务应用想获取当前的存活和就绪状态,将ApplicationAvailability接口autowire进来即可,下一篇《实战篇》会有详细的使用方式,这里看下关键代码:
    在这里插入图片描述

    监听状态

    得益于Spring完整的事件发布和订阅机制,业务应用通过EventListener注解就能监听到存活和就绪状态的变化,在EventListener注解修饰的方法中写入必要的业务代码即可实现状态监听,下一篇《实战篇》会有详细的使用方式,这里看下关键代码:
    在这里插入图片描述

    修改状态

  8. 修改状态,尤其是就绪状态,这应该是我们最关注的功能了,在某些业务场景下,应用无法对外提供服务,这时候我们希望K8S不要将外部请求调度到这里,如果K8S通过就绪探针收到返回码非200,就不再将请求调度到这个pod上;
  9. 下一篇《实战篇》会有详细的代码介绍,这里给出关键代码作为参考:
    在这里插入图片描述

    请注意

    重要的事情一定要强调:咱们修改状态的最终目的,不是为了取得applicationAvailability.getReadinessState()返回新的枚举对象,而是要改变/actuator/health/readiness接口的返回码(就绪是200,未就绪是503),这是kubernetes的探针规则要用到的;

    为啥都放在下一篇

  10. 文章看到这里您可能已经火冒三丈了:关键代码都贴出来了,为啥不在本章给出完整源码?骗点击量?凑字数?凑文章数?
  11. 存活和就绪探针是在kubernetes环境下的工具,为了给您提供尽量准确和完整的参考,所有的代码和操作都必须在kubernetes环境完成调试才能发布,而且这些操作应该作为单独章节,与当前的理论知识分开;
  12. 欢迎进入《实战篇》,随SpringBoot-2.3.0.RELEASE,一起在kubernetes世界畅游;

欢迎关注阿里云开发者社区:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
4月前
|
前端开发 Java 应用服务中间件
Spring Boot 2.x 嵌入式 Servlet 容器
Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。
|
4月前
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
5月前
|
Java API Docker
使用Spring Boot和Docker进行容器化部署
使用Spring Boot和Docker进行容器化部署
|
5月前
|
Java 应用服务中间件 Maven
SpringBoot(六)之内嵌容器
需要用哪个容器,就把其他两个容器注释掉。(
48 0
|
5月前
|
Java 应用服务中间件 容器
手写SpringBoot(二)之动态切换Servlet容器
我们在切换serlvet容器的时候,会将SpringBoot默认的tomcat jar包给排除掉,换上我们需要的jar包,比如jetty。
39 0
|
5月前
|
Java Docker 容器
springboot项目容器化
springboot项目容器化
|
6月前
|
存储 Java 应用服务中间件
Springboot项目打war包部署到外置tomcat容器【详解版】
该文介绍了将Spring Boot应用改为war包并在外部Tomcat中部署的步骤:1) 修改pom.xml打包方式为war;2) 排除内置Tomcat依赖;3) 创建`ServletInitializer`类继承`SpringBootServletInitializer`;4) build部分需指定`finalName`;5) 使用`mvn clean package`打包,将war包放入外部Tomcat的webapps目录,通过startup脚本启动Tomcat并访问应用。注意,应用访问路径和静态资源引用需包含war包名。
428 0
|
6月前
|
Java Maven Docker
【SpringBoot系列】SpringBoot应用程序容器化及容器优化
【4月更文挑战第4天】SpringBoot应用程序容器化及容器大小优化
99 0
|
6月前
|
Kubernetes 应用服务中间件 nginx
Kubernetes容器探针
Kubernetes容器探针
79 0
|
6月前
|
Java 应用服务中间件 API
【SpringBoot技术专题】「开发实战系列」Undertow web容器的入门实战及调优方案精讲
【SpringBoot技术专题】「开发实战系列」Undertow web容器的入门实战及调优方案精讲
184 0