ToB企服应用市场:ToB评测及商务社交产业平台

标题: 得物架构面试:怎样保证服务发布过程中流量无损? [打印本页]

作者: 来自云龙湖轮廓分明的月亮    时间: 2024-7-28 14:17
标题: 得物架构面试:怎样保证服务发布过程中流量无损?
哈喽,大家好,我是明智
  本日跟大家讨论一个服务稳固性相关的话题,对于大部门做业务的小同伴来说,很少会被问到这类问题
  不外你如果你盼望面试公司的一些基础部门,例如:基础架构、效能开辟、服务稳固性保障等,就很可能遇到
  笔者在前段时间的面试中就被问到了,这个问题还有一系列的问法,例如:
    本文重要分为以下几个部门
       ❝   本文只讨论K8s情况下的怎样做到优雅启停
    流量无损的关键

  发布过程中丧失的流量重要包罗:
    因此我们要保证流量无损,要做到以下几点
    K8s情况下怎样保证流量无损

  K8s中的滚动发布

  如果是Deployment ,可以通过设置 Deployment 的 rollingUpdate 计谋来控制滚动更新的行为。
  关键参数

  
  1. piVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: example-deployment
  5. spec:
  6.   replicas: 3
  7.   strategy:
  8.     type: RollingUpdate
  9.     rollingUpdate:
  10.       maxUnavailable: 1        # 在更新过程中最多允许 1 个 Pod 不可用
  11.       maxSurge: 1              # 在更新过程中最多允许额外创建 1 个 Pod
复制代码
如果是statefulSet,其滚动更新计谋由 updateStrategy 字段指定,重要有以下几个设置选项:
  
  K8s的三种探针

  我们利用这三种探针的目的在于:
    
     webp    Startup Probe   (启动探针):如果设置了启动探针,在进行启动探测成功之前,不会进行存活探测。如果启动探测失败,k8s会重启pod。启动探针探测成功后,Liveness Probe 和 Readiness Probe 将接管健康查抄。Startup Probe 适合用于那些启动时间较长的应用程序,防止它们在启动过程中被误判为失败。如果应用启动时间不是特别长,没有须要设置这个探针。
  Liveness Probe (存活探针):存活探测如果失败,K8s会重启Pod。重要用于检测可通过重启办理的故障,例如:服务端可用线程耗尽、死锁等
  Readiness Probe (停当探针):停当探测成功之后,才会将pod加入到svc的端点列表中。如果停当探测失败,会将pod从端点中剔除
  利用示例

  deployment文件添加探针:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. spec:
  4.   template:
  5.     spec:
  6.       containers:
  7.       # 在containers下添加两个指针
  8.         livenessProbe:
  9.           httpGet:
  10.             path: /actuator/health/liveness
  11.             port: 8080
  12.           # pod启动后延迟60s探测
  13.           initialDelaySeconds: 45
  14.           # 每30s测一次
  15.           periodSeconds: 10
  16.           # 每次探测最大超时时间3s
  17.           timeoutSeconds: 3
  18.           # 连续6次探测失败则重启pod
  19.           failureThreshold: 3
  20.         readinessProbe:
  21.           httpGet:
  22.             path: /actuator/health/readiness
  23.                   livenessProbe:
  24.             httpGet:
  25.               path: /actuator/health/liveness
  26.               port: 8080
  27.             initialDelaySeconds: 45
  28.             periodSeconds: 10
  29.             timeoutSeconds: 3
  30.             failureThreshold: 3
复制代码
留意事项

  1、添加liveness跟readiness探针后,如果组件状态异常,会导致pod重启, 在特殊场景下, 组件异常并不必要重启, 必要利用方自行判断。
  例如:redis挂掉, 但是在服务中, redis缓存允许穿透或者异常, redis挂掉不应该重启呆板, 这个在healthcheck中,redis状态异常不应该触发liveness和readness失败
  2、initialDelaySeconds的值应该根据应用启动时间进行公道设置,如果设置过短,会导致pod反复被kill无法正常启动
  K8s的preStopHook

  K8s杀死一个pod的过程

  在 Kubernetes Pod 的删除过程中,同时会存在两条并行的时间线,如下图所示。
    
     pod删除过程    网络层面

    Pod 层面

    由于网络层面跟pod层面的变更是并行的,二者状态的不同等,会导致pod在停机的过程中仍旧在接收流量。为了规避这个问题,我们必要利用到K8s提供的preStopHook
  
  引入preStopHook后,可以在pod杀死前,先执行preStopHook,在preStopHook中我们可以执行一个脚本,这个脚本可以简单的sleep一段时间,等待网络层变更完成后pod再响应SIGTERM信号,确保pod克制时,流量已经完全摘除,如下:
  1. spec:
  2.   contaienrs:
  3.   - name: my-awesome-container
  4.     lifecycle:
  5.       preStop:
  6.         exec:
  7.          command: ["sh", "-c", "sleep 10"] # 延迟关闭 10秒
复制代码
很多情况下,pod除了接收K8s调理的流量外,还会接收来自rpc的流量,例如:dubbo,这个时间,我们可以在实现一个负责的脚本,除了等待k8s网络层变更完成外,还必要将服务从注册中心中下限
  1. spec:
  2.   contaienrs:
  3.   - name: my-awesome-container
  4.     lifecycle:
  5.       preStop:
  6.         exec:
  7.           command: ["/bin/sh","-c","/pre-stop.sh"]
复制代码
    ❝   应用程序提供一个服务下线的借口,在pre-stop.sh中,可以调用这个接口,实现服务下线
    怎样验证

  这里我直接给出一个验证脚本,大家将其中的参数替换为服务核心接口的url即可:
  1. #!/bin/bash
  2. # 目标 URL
  3. url="your url"
  4. # 请求失败的次数计数器
  5. fail_count=0
  6. # 总请求次数计数器
  7. total_count=0
  8. # 日志文件
  9. log_file="request_log.txt"
  10. # 发送请求并统计失败次数的函数
  11. send_request() {
  12.     response=$(curl --silent --show-error --write-out "HTTPSTATUS:%{http_code}" "$url")
  13.     # 提取HTTP状态码
  14.     http_status=$(echo "$response" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
  15.     response_body=$(echo "$response" | sed -e 's/HTTPSTATUS\:.*//g')
  16.     timestamp=$(date "+%Y-%m-%d %H:%M:%S")
  17.  ((total_count++))
  18.     if [ "$http_status" -ne 200 ]; then
  19.         ((fail_count++))
  20.         echo "$timestamp - 请求失败, HTTP状态码: $http_status, 响应: $response_body" | tee -a "$log_file"
  21.     else
  22.         echo "$timestamp - 请求成功, HTTP状态码: $http_status, 响应: $response_body" | tee -a "$log_file"
  23.     fi
  24. }
  25. # 每秒钟发送一个请求
  26. while true; do
  27.     send_request
  28.     echo "失败次数: $fail_count,请求总次数:$total_count" | tee -a "$log_file"
  29.     sleep 1
  30. done
复制代码
  带来的影响

  接入优雅启停对服务最大的影响在于发布时间会延伸。发布时间包罗:新pod的启动时间+旧pod的终止时间
  如果按照以下设置:
  
  总结

  本文重要跟大家介绍了K8s情况下怎样实现服务的优雅启停来保证服务发布过程中流量无损,咱们不仅学会了怎么做,也知道了为什么要怎么做。
  在文中我有提到,要实现服务的优雅启停还必要服务自身正确的响应kill信息,其实就是K8s发出的SIGTERM信号,对应kill -15命令。
  服务正确响应SIGTERM信号要怎么做本文没有提到,别的本文只提到了怎样设置K8s的探针,但没有涉及到探针怎样实现。思量到篇幅缘故因由,关于应用自身必要做的变乱,我们放到下篇文章中。
  作者简介
    推荐阅读
  美团一面问我i++跟++i的区别是什么
  美团一面,你碰到过CPU 100%的情况吗?你是怎么处理的?
  美团一面:碰到过OOM吗?你是怎么处理的?
  美团一面,发生OOM了,程序还能继承运行吗?

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4