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

3720b96b19e16556060c8c811bc83b9a.gif

前言

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

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

流量调度、微服务可寻址性和注册中心_第1张图片

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

关键名词解释

  1. 1. 控制平面/数据平面[1]   

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

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

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

  1. 2. 东西/南北流量[2] 

  2.     南北流量:业务客户端--->服务器;
    东西流量:数据中心内或者数据中心之间的服务间调用;东西/南北流量都属于数据平面流量。

服务治理的演进

流量调度、微服务可寻址性和注册中心_第2张图片

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

阶段 目标 手段
孵化期 动态服务发现 客户端/服务端服务发现,负载均衡
成长期 提高开发和迭代效率 规范API、 统一配置、 版本管理
成熟期 部署边界、链路追踪,弹性伸缩 服务预热、优雅下线、监控追踪、限流,熔断, 回退

核心的技能点

  1. 1. 为什么需要注册中心?
    并不是微服务催生了 注册中心,而是微服务强化了注册中心。 

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

  3.    这里面有一个addressability的概念,服务可寻址性[4], 每个微服务必须有一个唯一的可寻址的名字,动态表征一组可以处理流量的实例资源。 

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

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

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

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

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

  4.     存在两种模式:  客户端服务发现、服务器服务发现,   

  5.     核心区别在于 :客户端是否保存服务列表信息。

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

  • • 微服务调用方寻址

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

流量调度、微服务可寻址性和注册中心_第3张图片 流量调度、微服务可寻址性和注册中心_第4张图片
  1. 4. 负载均衡

  • • 随机

  • • 轮询

  • • 带权轮询

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

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

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

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

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

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

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

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

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

大多数时候,流量其实不care某个特定的应用实例,更在意的是服务的可用性; 负载层需要做到无损扩缩容,无损切流,这些都涉及动态上下线实例。

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

服务端服务发现,在客户端和接流应用之间新增了一个负载层,除了负载均衡外,还提供了故障转移和无损切流的契机。不同负载层有不同的接流姿势。

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

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

流量调度、微服务可寻址性和注册中心_第5张图片

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

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

利用nginx的第三方组件nginx_http_dyups_module[6],可以做到动态修改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. 1. 该组件默认不被编译进tengine(淘宝开源的具备强特性的nginx分发版),请使用--with-http_dyups_module配置参数启用。

./configure --add-module=./modules/ngx_http_upstream_dyups_module              // 配置成静态组件
 make             // 编译
 make install     // 安装
  1. 2. 需要添加dyups_interface指令激活[动态修改upstream配置]能力。

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

查询upstream:localhost:8081/detail

test_upstream
server 127.0.0.1:8088 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
server 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_upstream
server 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的理解,限于篇幅,战术性动作没有展开,路漫漫其修远兮,文辞拙劣,如果错误或者不同见解,欢迎留言探讨。

引用链接

[1] 控制平面/数据平面: https://geek-docs.com/network/network-ask-answer/difference-between-control-plane-and-data-plane.html
[2] 东西/南北流量: https://zhuanlan.zhihu.com/p/40677776
[3] 阿里云服务治理的演进: ![](https://files.mdnice.com/user/4236/def59f88-cbba-49e2-b941-a63e3db6679c.png)
[4] 服务可寻址性: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/microservices-addressability-service-registry
[5] Host请求头在虚拟主机服务多网域服务中的关键作用: https://www.cnblogs.com/JulianHuang/p/16639016.html
[6] nginx_http_dyups_module: http://tengine.taobao.org/document_cn/http_dyups_cn.html

点“流量调度、微服务可寻址性和注册中心_第6张图片戳“在看流量调度、微服务可寻址性和注册中心_第7张图片

体现态度很有必要!

你可能感兴趣的:(微服务,java,运维,架构,云原生)