码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 如何优雅的利用k8s探针解决注册中心服务短暂不可用?


    一、容器探针

    k8s中probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。

    检查机制

    使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:

    exec:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。

    grpc:使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 "GRPCContainerProbe" 特性门控时才能使用。

    httpGet:对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。

    tcpSocket:对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。

    探测结果

    每次探测都将获得以下三种结果之一:

    Success(成功)容器通过了诊断。

    Failure(失败)容器未通过诊断。

    Unknown(未知)诊断失败,因此不会采取任何行动

    探测类型

    针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:

    livenessProbe:指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。

    readinessProbe:指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。

    startupProbe: 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。

    二、通过探针优雅的解决服务部署过程中注册中心服务平滑过渡问题

            我们后端采用Spring Cloud(Spring Cloud Alibaba)微服务结构技术路线进行开发,采用nacos作为注册中心。而服务注册到nacos是需要时间的,经过测试大约在3分钟左右,而一般的容器探测只是探测服务是否达到了可用的状态,没有采用注册中心的这种服务自然是一般的就绪性探测或者存活性探测或者启动探测都可以实现。这种探测在于即使探测服务可用了,但是并没有及时注册进注册中心中,若是只有一个pod的情况下,在容器探测成功后,新的pod变成了可用状态了,便停掉了第一个pod,但是这个时候服务并没有注册到注册中心,就造成了服务短暂不可用。

    SpringBoot的actuator

    其实actuator是用来帮助用户监控和操作SprinBoot应用的,这些监控和操作都可以通过http请求实现,如下图,http://localhost:7777/actuator/health地址返回的是应用的健康状态

     需引以下maven:

    1. org.springframework.boot
    2. spring-boot-starter-actuator

    在SpringBoot-2.3版本中,actuator新增了两个地址:/actuator/health/liveness和/actuator/health/readiness,前者用作kubernetes的存活探针,后者用作kubernetes的就绪探针,需要先在配置文件中开启,如下:

    1. management:
    2. endpoint:
    3. health:
    4. probes:
    5. enabled: true
    6. health:
    7. livenessstate:
    8. enabled: true
    9. readinessstate:
    10. enabled: true

     利用SpringBoot的接口来作为容器探针的健康检测,按照如下就可:

    1. readinessProbe:
    2. initialDelaySeconds: 20
    3. periodSeconds: 10
    4. timeoutSeconds: 5
    5. failureThreshold: 6
    6. httpGet:
    7. scheme: HTTP
    8. port: 9999
    9. path: /actuator/health/readiness
    10. livenessProbe:
    11. initialDelaySeconds: 30
    12. periodSeconds: 10
    13. timeoutSeconds: 5
    14. failureThreshold: 6
    15. httpGet:
    16. scheme: HTTP
    17. port: 9999
    18. path: /actuator/health/liveness

    自己编写容器探针接口

    1. /**
    2. * @author BD-PC40
    3. * @version 1.0
    4. * @description: 容器探针接口,用来进行探测服务是否注册进入注册中心
    5. * @date 2022/7/12 10:58
    6. */
    7. @Slf4j
    8. @RestController
    9. @RequestMapping("nacos")
    10. public class HealthController {
    11. @Autowired
    12. private DiscoveryClient discoveryClient;
    13. @GetMapping("/health/{services}")
    14. public ResponseEntity getService(@PathVariable("services")String services) throws NacosException {
    15. //从nacos中根据serverId获取实例 方法一(采用此方法,DiscoveryClient 代表的就是:服务发现操作对象)
    16. if (StringUtils.isBlank(services)){
    17. return new ResponseEntity(HttpStatus.BAD_REQUEST);
    18. }
    19. List instances = discoveryClient.getInstances(services);
    20. Map ipMap = new HashMap<>();
    21. if (instances.size() > 0){
    22. instances.forEach(key ->{
    23. ipMap.put(key.getHost(), key.getPort());
    24. });
    25. }
    26. //从nacos中根据serverId获取实例 方法二 采用nacos的java的SDK
    27. // Properties properties = new Properties();
    28. // properties.put("serverAddr", "192.168.4.25:8849");
    29. // properties.put("namespace", "caseretrieval-dev");
    30. // NamingService naming = NamingFactory.createNamingService(properties);
    31. // List instancesList = naming.selectInstances("case-gateway", true);
    32. //从nacos中根据serverId获取实例 方法三,采用nacos的OPEN-api
    33. //http://192.168.4.25:8849/nacos/v1/ns/instance/list?serviceName=case-gateway&namespaceId=caseretrieval-dev
    34. //获取本机IP地址
    35. String hostAddress = "127.0.0.1";
    36. try {
    37. InetAddress localHost = InetAddress.getLocalHost();
    38. hostAddress = localHost.getHostAddress();
    39. log.info("当前服务本机ip是:"+hostAddress);
    40. } catch (UnknownHostException e) {
    41. log.error(e.getMessage(), e);
    42. }
    43. //查看本机服务是否已经注册到nacos中
    44. if (ipMap.containsKey(hostAddress)){
    45. return new ResponseEntity(HttpStatus.OK);
    46. }else {
    47. return new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);
    48. }
    49. }
    50. }
    51. 相关阅读:
      latex图片在双栏文档中横跨两栏
      买卖股票的最佳时机-贪心/动态规划-Java/python
      2022最新RTMP+HTTP直播地址汇总(亲测可用)
      华为摄像头智能安防监控解决方案
      uni-app+vue3+ts项目搭建完整流程
      node中文件的上传
      linux平台的无盘启动开发
      测开要做的开发工作到底是做什么
      echarts看板效果图:流光折线图、3d柱状图、3d饼图
      阿里SQL规约
    52. 原文地址:https://blog.csdn.net/m0_37044606/article/details/125788345
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号