写点什么

流量调度、微服务可寻址性和注册中心

  • 2023-03-24
    四川
  • 本文字数:2622 字

    阅读完需:约 9 分钟

前言

现代计算机基于计算、存储和调度的体系, 于是现代架构都是围绕这三大话题不断演进。


在基础架构部, 也是主要为了解决这三个难题,为业务事业部提供透明的、高可用、可快速伸缩的 三大能力, 我们组主要负责 [流量调度] 这个话题,下面是一些宏观的技术笔记。



在单体结构, 流量调度是直观且无感的(DNS+Nginx 就可以完成一次流量调度)。演进到 微服务结构(服务粒度变得更细、服务伸缩更灵活(上下线更加频繁),团队松耦合),流量调度并没有消失,而是变得更加复杂。

关键名词解释

  1. 控制平面/数据平面

  2. 控制平面: 内含路由表、负责路由控制, 引导流量的走向,注重“引导”, 属于旁路业务(核心)。

  3. 数据平面:根据控制平面的路由逻辑,业务流量的实际走向。


控制面很多属于[核心]旁路业务:要求一致性=> raft 协议。


  1. 东西/南北流量

  2. 南北流量: 业务客户端--->服务器;

  3. 东西流量: 数据中心内或者数据中心之间的服务间调用;

  4. 东西/南北流量都属于数据平面流量。

服务治理的演进


服务治理的基石是动态服务发现, 阿里云服务治理的演进 大而全,这里只记录我的理解。


核心的技能点

  1. 为什么需要注册中心?

  2. 并不是微服务催生了 注册中心,而是微服务强化了注册中心

  3. 早期 DNS+nginx 就能完成单体的 流量调度,但是不管是 DNS 解析出 ip, 还是 nginx 解析出 upstream ,底层都有注册中心的影子。

  4. 这里面有一个 addressability 的概念,也即服务可寻址性, 服务必须有一个唯一的可寻址的名字,这个名字不依赖于部署环境,表征一组可以处理流量的实例资源。

  5. 对于资源,必定存在 CRUD 交互,这便是部署平台和服务发现,与此同时当实例出现故障时,注册中心必须能够指示服务现在在何处运行。


部署层面一般存在健康探测告知业务方目前的应用就绪情况; 实际在接流的时候,负载层还会有自己的主动健康检查探测。


  1. 规范 API 接口, 统一配置

  2. 提高开发迭代效率,统一使用一种 method、body payload 形式的 API 接口(规避错误格式的传参导致的撕逼)、不用上 n 台实例修改配置。


各个团队是松耦合的关系,上下游的变更并不会主动通知,故需要版本管理(低版本不能直接下线)、提供给开发团队的版本调试接口。


  1. 服务发现

  2. 服务发现是服务治理的基石,三板斧: 注册、心跳、寻址。

  3. 部署系统做[注册]动作。

  4. 微服务客户端寻址

  5. 主动上报心跳/注册中心主动探活: 维护实例资源状态。

  6. 存在两种模式: 客户端服务发现、服务器服务发现, 核心区别在于 : 客户端是否保存服务列表信息。




  1. 负载均衡


  • 随机

  • 轮询

  • 带权轮询

  • 根据后端实例服务质量动态调度


最近思考了一个问题,负载均衡不仅是拿到服务的可用实例列表,然后做流量均分; 其实负载均衡的存在也为我们无损切流提供了契机。


  1. 飞机起飞和降落最容易出事故


  • 服务预热: 服务进程启动,等待业务配置/缓存就绪,再向注册中心通报实例资源就绪,可以接流。

  • 优雅下线: 下线时设置服务终止时间(30s),处理在途流量, 不再接收新的请求流量。


  1. 限流 熔断

  2. 链路上部分服务的状态会影响整个链路(雪崩), 故需要保障微服务链路的高可用 => 服务的熔断、限流


熔断: 熔断掉对于下游的调用; 限流: 限制进入本应用的流量。


不管是客户端服务发现,还是服务器服务发现,都存在注册中心,也可以叫名字服务,是流量调度的基石,统一了流量调度的入口。


现代互联网结构,流量在打到应用之前,都会以对应的姿势接入某种负载层。


大多数时候,流量其实不 care 某个特定的应用实例,更在意的是服务的可用性;


服务端服务发现,在客户端和接流应用之间形成了一个负载层,除了负载均衡外,还提供了故障转移和无损扩缩容、无损切流的契机,这些都涉及动态上下线实例, 不同负载层有不同的接流姿势。

基于 nginx7 层负载的动态服务发现

我们着重聊一聊基于 nginx 主机名字的动态服务发现(服务端服务发现)。


nginx 做反向代理,负载均衡的时候,我们关注 nginx [http 配置节]的上下文[server 配置节][upstream 配置节]。



上面这个配置,nginx 会匹配请求的Host头server_name指令,决定该请求转发给哪一个upstream虚拟主机。


相关知识,请关注Host请求头在虚拟主机服务多网域服务中的关键作用


利用 nginx 的第三方组件nginx_http_dyups_module,可以做到动态修改 upstream 的配置。


This module can be used to update your upstream-list without reloadding Nginx.


daemon off;error_log logs/error.log debug;
events {}
http { upstream test_upstream { server 127.0.0.1:8088; server 127.0.0.1:8089; }
server { listen 80;
location / { # The upstream here must be a nginx variable set $up test_upstream ; proxy_pass http://$up; } }
server { listen 8088; location / { return 200 "8088"; } }
server { listen 8089; location / { return 200 "8089"; } }
server { listen 8090; location / { return 200 "8090" ; } }
server { listen 8081; location / { dyups_interface; } }}
复制代码


  1. 该组件默认不被编译进 tengine(淘宝开源的具备强特性的 nginx 分发版),请使用--with-http_dyups_module配置参数启用。


./configure --add-module=./modules/ngx_http_upstream_dyups_module              // 配置成静态组件 make             // 编译 make install     // 安装
复制代码


  1. 需要添加dyups_interface指令激活[动态修改 upstream 配置]能力

  2. 演示利用 dyups api 在不重启 nginx 的情况下修改 upstream 配置。


查询 upstream 和 server:localhost:8081/detail


test_upstreamserver 127.0.0.1:8088 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0server 127.0.0.1:8089 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
// 实际请求`curl 127.0.0.1`,轮询返回8088或者8089
复制代码


更新 upstream 配置:curl -d "server 127.0.0.1:8090;" 127.0.0.1:8081/upstream/test_upstream


 // 再次调用`localhost:8081/detail` test_upstreamserver 127.0.0.1:8090 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0// 实际请求`curl 127.0.0.1`,轮询返回8090
复制代码


以上是对于流量调度这个大的 topic 的理解,限于篇幅,战术性动作没有展开,路漫漫其修远兮,文辞拙劣,如果错误或者不同见解,欢迎留言探讨。

发布于: 刚刚阅读数: 4
用户头像

急性子,入戏慢。 2018-06-17 加入

阿里云社区专家博主,同程旅行基础架构 ; 热衷分享,执着于阅读写作,佛系不水文,有态度公众号:《精益码农》; 持续输出高价值Go、.NET、云原生原创文章。

评论

发布
暂无评论
流量调度、微服务可寻址性和注册中心_有态度的马甲_InfoQ写作社区