关于负载均衡的路径信息该在哪个节点维护
一般来说数据流有 3 个区域: 客户端 -> 负载均衡器(lb) -> N 个上游服务器(service)
路线一: 在客户端配置
-
一般模式: 客户端请求的 header 头内有一个字段包含 service 的标记, lb 根据这个标记转发到不同的服务器;
这个标记一般是个 cookie, lb 查询本地映射关系后转到指定的服务器;
如果连 lb 这里的映射信息也不想维护, 干脆可以在这个标记里面写明 server 的 ip
这个标记首次是怎么来的呢?可以是客户端内置的一个列表, 也可以是首次访问时 lb 随机指定; -
特殊模式: 客户先请求一个接口, 获取一个地址列表, 然后选一个再发起业务请求, 例如 DNS
优点: 简单, 可控, 客户端调试时很容易定位到这个请求是哪个服务器处理的;
缺点: 极端情况下变更服务节点可能需要同时改这三个区域的配置;
路线二: 在 LB 上配置
传统的 nginx, haprox 等都是这样做的; 即 LB 根据自身独立的路径配置规则然后转发到后端;
优点: 好理解, 可控程度高
缺点: 后端变更后(如新增节点), 需要再改一次 lb 的配置
路线三: 在后端服务上配置
核心是 lb 动态获取后端服务的变化, 有多种细分实现方法;
-
方法一: lb 提供一个接口, 后端服务上线时自动去 lb 上注册, 下线时主动注销;
-
方法二: 有一个公共注册中心或配置中心(etcd, consul, redis, eureka, mysql 等),
service 去注册和注销, lb 动态去拉取更新, 或者是 lb 进行 watch 监听;这两个方法都存在的问题: 程序异常停止没主动下线时的问题, 需要配合健康检查;
-
路线三: 和方法二差不多, 但 lb 不是监听注册中心, 而是监听 docker, kubernetes 等组件的 api, 服务一有变动立即可知; 程序内部不需要引入注册类的库, 历史老旧应用无需改造即可适配, 特别适合云原生环境;
优点: 一次变更只需要后端的服务改一次
缺点: 假设某个节点服务异常, 希望隔离流量待排查, 而不是直接下线服务时, 比较麻烦;
路线选择
根据实际情况选
- 绝对性能型优先客户端负载
- 可控型优先 lb 配置
- 自动化程度要求高就由后端配置
- 如果是云原生或微服务场景更推荐路线三