k8s 在 tomcat 多副本时的 session 会话保持
出现问题
通过 kubernetes 部署了 tomcat+mysql 服务,设置 tomcat 多副本时发现首页登陆无法跳转的情况,经排查是由于 session 问题引起的。
kubernetes 上可以多实例(pod)高负载运行,但是如果应用如果没有做 session 同步的话,就会导致 session 不一致。
kubernetes 有 session 亲和性的功能(每个 client 每次访问,都会匹配到对应 session 的后端)。
解决方案
此时,在 service 的配置文件中加入 sessionAffinity: ClientIP
,功能是选择与请求来源 ip 更接近的 pod,这样就会固定同一个 session。
如下图所示:
备注:这种方法目前只适用使用 nodeport 暴露服务的情况。
spec.sessionAffinity
字段用于定义要使用的粘性会话的类型,它仅支持使用 “None” 和 “ ClientIP” 两种属性值。
也可以使用打补丁的方式进行修改 yaml 内的内容,如下:
# session保持,同一ip访问同一个pod
kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClusterIP"}}'
# 取消session
kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}'
Session 超时时间
Service affinity 的效果仅仅在一段时间内生效,默认值为 10800 秒,超出时长,客户端再次访问会重新调度。
该机制仅能基于客户端 IP 地址识别客户端身份,它会将经由同一个 NAT 服务器进行原地址转换的所有客户端识别为同一个客户端,由此可知,其调度的效果并不理想。
Service 资源 通过 .spec.sessionAffinity
和 .spec.sessionAffinityConfig
两个字段配置粘性会话。
如果您还想指定时间,则需要添加以下内容:
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10
Session Affinity
会话保持 (Session Affinity), 有时又称粘滞会话 (Sticky Sessions), 是负载均衡领域设计需要着力解决的重要问题之一,也是一个相对比较复杂的问题。
会话保持是指在负载均衡器上的一种机制,在完成负载均衡任务的同时,还负责一系列相关连的访问请求会分配到一台服务器上。
当用户向服务器发起请求,服务器创建一个 session,并把 session id 以 cookie 的形式写回给客户。