得物社区的微服务流量治理演进之路

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. POIZON 得物社区的微服务流量治理演进之路 得物-社区后端技术 赵旸(York)
2. POIZON 目录 01 得物社区微服务概览 02 出道即巅峰?—— Service Mesh 阶段 03 04 05 Istio下线历程 小得物流量治理 未来展望:殊途同归
3. POIZON 01 得物社区微服务概览
4. POIZON 首页推荐流 1.1 得物社区业务概览 动态详情页 国内最大潮流文化社区 聚集最懂潮流的年轻人 提升一代年轻人的潮流审美 帮助年轻人找到自己的风格 100 + 当红明星引领潮流风尚 100w + 潮流爱好者晒出开箱 500+品牌官方账号 500+认证专业达人
5. POIZON 1.1 得物社区业务概览 业务架构 C端 Feeds流、内容基础、用户基础、 创作者、发布工具、互动、活 动、搜索、商业化等 中后台 审核、内容标签、内容理解、宽 表聚合、生态治理等 另外还有直播、鉴别讨论区、交 易搭配等泛社区业务,大量微服 务整体对外提供业务支撑
6. POIZON 1.2 微服务部署 应用生命期管理 微服务部署在阿里云上,基于 Kubernetes 做应用的生命周期管理,包括部署、扩缩容、自动恢复、发布等, Kubernetes 为微服务提供了可扩展、高弹性的部署和管理平台。 持续集成与发布 使用自研的SCM(基于gitlab)做分支管理和代码检查,在得物发布平台里选择分支和要部署的环境进行持续集 成、或通过手动发布来触发Jenkins pipeline,自动编译代码并打包成docker镜像推送到Harbor镜像仓库、生成 应用的 Kubernetes YAML配置文件、更新 Ingress 配置等,最后调用 Kubernetes 的API来部署应用。 问题: • 微服务之间如何互相发现 • 南北/东西流量 • http/rpc 负载均衡 • Service 流量细粒度控制 • 灰度发布
7. POIZON 02 出道即巅峰? —— Service Mesh 阶段
8. POIZON 2.1 第一阶段:Service Mesh 老集群 2020年Q1-Q3 引入 Service Mesh 原因: traffic • SDK开发门槛、版本升级和兼容性 • 历史技术债导致缺乏治理能力 SLB • 业务开发可以专注于业务逻辑 • 南北流量:SLB -> Istio Ingress Gateway -> Pod(sidecar -> App) • 东西流量:Pod(App -> sidecar) -> Pod(sidecar -> App) Gateway Istio Ingress Gateway (Envoy) configures Destination Rule Virtual Service get endpoints external traffic Pod sidecar Pod Pod IP:port sidecar svc name:port App App Service Mesh 将流量管理从 Kubernetes 中解耦 Service track associated pod instances Endpoints
9. POIZON Pod IP: 10.40.0.18 Pod IP: 10.40.0.15 Pod Pod ① App Get http://reviews:9080/xx 2.2 Service Mesh端到端调用分析 App svc name: reviews iptables redirect ② Port:15001 Envoy Envoy ③ VirtualOutboundListener ④ Outbound Listener 0.0.0.0_9080 ⑤ ⑥ ⑦ 找不到和请求目的地端 口匹配的 Listener? Inbound Cluster: inbound|9080|http|reviews… filter chain Route:9080 Endpoint: 127.0.0.1:9080 Route 匹配不到 OutboundCluster? VirtualInboundListener filter chain Outbound Cluster: outbound|9080||reviews… ② 请求被iptables规则拦截,重定向到本地的15001 端口 ③ 在15001端口监听的Envoy使用VirtualOutbound Listener处理请求 ④ 请求被VirtualOutboundListener根据原目标IP (通配)和端口(9080)使用0.0.0.0_9080这个 outbound listener继续处理 ⑤ 每个Listener会定义一组filter,共同组成过滤器链 (filter chain)来执行高阶的流量控制,例如转换 协议消息、生成统计信息、限流等。根据listener 中http_connection_manager filter的配置,该请 求采用“9080”route进行分发 ⑥ Route是一组将虚拟主机(virtual hosts)与集群 (cluster)匹配的规则。 virtual hosts = domain + path。本例中将domain为reviews的请求匹配到的 cluster是 outbound|9080||reviews.default.svc.cluster.local ⑦ Cluster是服务集群,包含endpoints,envoy通过 Cluster来实现流量的负载均衡,会定期轮询CDS来 获取/更新配置 兜底措施: Port:15006 Endpoint: 10.40.0.15:9080 ① 调用端发起http请求,对端svc name: reviews, port: 9080 iptables redirect PassthroughCluster【关键】 • • global.outboundTrafficPolicy.mode : ALLOW_ANY 匹配到的所有出流量都会被直接放行 BlackHoleCluster • • global.outboundTrafficPolicy.mode : REGISTRY_ONLY 匹配到的所有出流量都会被直接丢弃
10. POIZON Pod IP: 10.40.0.18 Pod IP: 10.40.0.15 Pod Pod ① App Get http://reviews:9080/xx 2.2 Service Mesh端到端调用分析 App ⑧ 请求被转发到其中一个endpoint 10.40.0.15:9080 svc name: reviews ⑬ iptables redirect ② Port:15001 Envoy ③ ④ ⑤ ⑥ Envoy VirtualOutboundListener Outbound Listener 0.0.0.0_9080 ⑫ ⑪ filter chain Route:9080 ⑩ Endpoint: 127.0.0.1:9080 Inbound Cluster: inbound|9080|http|reviews… VirtualInboundListener filter chain ⑦ Outbound Cluster: outbound|9080||reviews… Port:15006 ⑧ Endpoint: 10.40.0.15:9080 ⑨ iptables redirect ⑨ 请求到达对端pod后被iptable规则拦截,重定向到 本地的15006端口 ⑩ 在15006端口上监听的Virtual Inbound Listener 收到了该请求,将直接在 VirtualInboundListener 采用一系列 filter chain 对入向请求进行处理,而 不是像 VirtualOutboundListener 一样分发给其 它独立的 listener 进行处理 ⑪ 根据http_connection_manager filter的配置,转 给 inbound|9080|http|reviews.default.svc.clust er.local 这个Inbound Cluster ⑫ 该Inbound Cluster配置的endpoint为 127.0.0.1:9080 ⑬ 请求被转发到和sidecar同一个pod上的9080端 口,即reviews服务进行业务处理 Service Mesh对服务间流量通讯进行了抽象,把复杂 的治理能力下沉到不与业务耦合的proxy中。 额外消耗 • 资源:代理容器 • RT:上下行各多了一跳
11. POIZON 2.3 Service Mesh与侵入式框架比较 Service Mesh 侵入式框架 社区服务当时的实际情况 学习门槛 低,独立的sidecar在网络层拦截完成流量控制和 高,需要学习和理解远程通信、服务注册发现、负载 服务治理工作,让上层业务开发只专注于业务逻辑 均衡、监控、熔断限流等技术 功能齐全 细粒度的流量控制,如蓝绿发布、金丝雀发布、故 生态成熟,从注册中心到监控中心各环节的中间件一 障注入等,完善的可观察性、安全控制 应俱全,一整套体系已经在业界打磨和运作多年 Istio服务治理方面的高级特性得 物有其他替代方案,并非刚需 跨语言 不限制语言,统一的通信策略 社区服务纯Golang技术栈,没 有跨语言的诉求 运维效率 对运维要求高,包括sidecar注入、热升级、启动 顺序、容量管理、监控、回滚摘流、安全性等,配 传统运维方式,经验和效率是优势 置过于复杂 Istio配置复杂,因为配置变更出 过多次故障 问题排查 对业务研发较为“黑盒” 排查手段更可控、定位问题更快 对业务研发太“黑盒”,比如外 网流量都没打到业务容器,要去 找运维查,沟通成本高 升级效率 热升级sidecar对业务基本无感知 需要推动业务升级框架,重新部署上线 基本没有升级 通过sidecar,端到端延迟增加 约4ms,有损耗但不是瓶颈 需要开发各种语言的sdk 性能 通过代理进行通信,增加延迟和CPU开销 端到端直接通信,没有proxy网络拦截,性能更好 可定制化 对上层业务较难定制化 可定制更贴合个性化业务场景的流量策略、观测性、 可用性(超时重试、限流熔断)策略
12. POIZON 2.4 Service Mesh增大了系统复杂度和排查难度 举例:一次RT抖动问题排查过程 ① 一次直播某服务RT抖动,从监控指标发现该服务全部接口RT和 全部pod的goroutine都上涨明显,首先判断影响范围为服务 级别。且同k8s集群中其余服务正常,排除网络原因;所有的 流量出入接口都受到影响,但下游依赖服务正常,也排除了依 赖服务故障。 ② 首先考虑系统资源是否充足,通过查看应用的cpu、memory 指标,判断告警时间点系统资源不存在瓶颈。这里业务研发一 般只关注自己应用的状态,因而对资源情况产生了误判,以为 是数据层存在故障。 ③ 但查看数据存储的性能趋势显示正常,且使用同样数据存储的 另一服务告警时段处于正常,因此不是数据层的问题。 ④ 服务扩容后RT抖动也恢复正常,所以还是将目光转 向流量路径,最后查看istio-proxy的负载,定位了 告警原因:sidecar负载过高导致了此次抖动。 问题根因:sidecar和业务容器 资源配比问题。 历史原因sidecar注入时固定 2c1g配置,业务容器原先是 1c512m,但随着业务量增长 该服务pod数过多。开发当日 升配了业务容器到4c2g,在总 核数不变情况下pod缩到原来 的1/4,每个pod里的sidecar 承担的流量同期扩大了4倍,高 峰期负载打满。
13. POIZON 03 Istio 下线历程
14. POIZON 3.1 两种方式并行:加入dubbo-go 老集群 2020年Q4-2021年Q3 traffic 通过服务发现在nacos中拿到Provider的 ip和port,流量还是要经过sidecar,转发 SLB 到目标pod,再通过sidecar到达目标服务 Istio Ingress Gateway (Envoy) external traffic Pod sidecar Pod Pod IP:port Pod sidecar sidecar svc name:port App Pod Pod IP:port sidecar Pod IP:port App App App dubbo-go dubbo-go 引入dubbo-go,主要使用了grpc server/client和注册中心功能 nacos
15. POIZON 3.2 下sidecar 老集群 2021年Q4 traffic 先到SLB,Istio Ingress Gateway作为proxy转发到目标pod grpc without dubbo-go SLB Istio Ingress Gateway (Envoy) 通过服务发现在nacos中拿到Provider的ip和port,直接转发到目标 pod,没有 proxy 的额外“一跳” Pod Pod App external traffic http Pod App Pod App Pod IP:port dubbo-go App dubbo-go 集群内http调用走的是k8s service域名解析,利用k8s的dns 和service负载均衡能力 nacos
16. POIZON 3.3 迁移kubeone&下Gateway 新集群 2022年Q1 traffic grpc without dubbo-go SLB 利用集群迁移机会,用Nginx Ingress Controller 代替 Istio Ingress Gateway,彻底下线 Istio Ingress Controller (Nginx) Pod Pod tools-c log-c App http tools-c log-c App Pod tools-c log-c App Pod Pod IP:port dubbo-go external traffic 新集群使用神龙7,性能提升明显 tools-c log-c App dubbo-go nacos
17. POIZON 3.4 坑点:grpc负载均衡 grpc负载均衡问题 grpc使用http2在同一连接和双工流中复用请求避免最初的时间和资源花费在TCP握手上,当客户端获取与服务器实例的连接时它将保持连接。 这是grpc的优点,但也带来负载均衡的问题。istio/envoy实现了grpc在pod间的负载均衡,下掉 istio 就必须解决这个问题。通常有两种方式 实现grpc负载均衡: 优点: 优点: • 客户端简单,无需感知后端 • 性能好,消除了额外一跳 服务 • 分布式,去中心化,适合大 流量场景 缺点: a. Proxy load balancing • 多了一跳,更高延迟 缺点: • LB中心化可能成为瓶颈 • 客户端复杂:跟踪后端负载 b. Client-side load balancing(首选) 又叫Server-side load balancing,LB追踪后端服务 客户端进程感知可用的后端服务并且实现负载均衡: 负载并实现负载均衡: ① 客户端直接向后端服务起RPC请求,没有额外开 ① 客户端向LB发起RPC请求 ② LB将请求转发给后端某个可用的服务 ③ 后端服务将负载报告给LB 销,性能比较好 ② 后端服务的负载和运行情况要能让客户端追踪到 和运行状况,实现负载均衡 • 每种语言客户端的实现负担
18. POIZON 3.4 坑点:grpc负载均衡 未接入dubbo-go的服务间的grpc调用 社区域通过grpc方式调用同集群内其他业务域(增长、鉴别)未集成dubbo-go的服务,下掉Istio sidecar后首先尝试 Client-side load balancing 解决grpc负载均衡问题 方式一:PickFirst(默认) PickFirst 是 golang grpc 默认的LB策略,如果直接通过 grpc.Dial(“k8s service name”)的方式去创建 ClientConn,只 会选取 service 后端 pods 中的一个进行连接 特点:客户端与服务的所有pod间只有一条长连接 坑点:往 ClientConn 上发请求,流量都会打到后端同一个pod上 方式二:RoundRobin + headless service(尝试使用) RoundRobin 是 golang grpc 内置支持的另一种LB策略,可以通 过grpc的DialOption指定:
19. POIZON 3.4 坑点:grpc负载均衡 未接入dubbo-go的服务间的grpc调用 社区域通过grpc方式调用同集群内其他业务域(增长、鉴别)未集成dubbo-go的服务,下掉Istio sidecar后首先尝试 Client-side load balancing 解决grpc负载均衡问题 方式二:RoundRobin + headless service RoundRobin策略一般与k8s的headless service一起配套使用: • “dns:///greeter_server”,其中通过URI scheme决定使用何 种grpc resolver插件来做名字解析,这里选择DNS • headless service,配置clusterIP为None,DNS解析service域 名拿到后端pod的真实IP列表 • grpc为每个后端地址创建一个subchannel,并持续监视这些子 通道的连接状态,断开时会重连 • 当发起RPC请求时,会从状态为READY的subchannel中轮流选 择发送 trick - MaxConnectionAge (不推荐) : grpc在长连接断开时会 re-resolve 重新建立连接,可以利用这个特性在服务 端设置keepalive.MaxConnectionAge,周期性断开连接来触发刷新,例如: 特点:客户端与服务的每一个pod都保有一条长连接 坑点:新扩容上去的pod很久都没有流量进来 • 服务扩容的时候,新实例并不会加入其中,需现有连接断开时才 能触发grpc重新连接 • DNS如coredns本身有缓存,且没有 watch 或 push 机制,压 根没有服务发现场景下的优化
20. POIZON 3.4 坑点:grpc负载均衡 未接入dubbo-go的服务间的grpc调用 最终还是选择 Proxy load balancing 方式,Nginx在1.13.10 中已增加了对 grpc 的原生支持,但是 官方文档中提到它当前支持的 grpc流量必须 基于ssl,不支持在80端口中复用HTTP1/1和HTTP2,内部grpc服务是监听非安全端口8080 解决方案: • nginx ingress controller使用安全端口443端口支持http2 • grpc 使用 tls,并在代理层摘掉 tls,转发给内部服务的非安全端口8080 扩容和缩容grpc负载均衡均符合预期
21. POIZON 04 小得物流量治理
22. POIZON 4.1 小得物环境简介 什么是小得物环境? 小得物环境是一套全新搭建、物理隔离的[小流量][生产环境],覆盖了从网络(VPC)、接入层(SLB/DLB)、中间件(dubbo/consul)、核心应用的系 统和服务,为各类产品研发和业务发展的稳定性提供了丰富工具和应用场景。
23. POIZON 4.2「小得物-生产」双集群架构 智能DNS解析 根据出口IP 将部分流量劫持至xdw 1% app.dewu.com 社区小得物环境 DLB中配置基于userid等 信息的二次灰度规则 网关精确路由配置与生产共用 在xdw网络环境上将内网域名 DNS劫持至xdw-internal DLB xdw-internal DLB负责配置 path转发,将未部署小得物的 应用转发至生产 诉求:RPC优先访问小得物服 务,小得物没有则访问生产服务 99% 社区生产环境 XDW DLB PRD DLB XDW APP gateway XDW APP gateway xdw-internal DLB 未命中去生产 SLB SLB Ingress Controller Ingress Controller Service 跨环境RPC Service
24. POIZON 4.3 小得物流量路由 自定义grpc Resolver、Balancer实现 Resolver 负责向 Balancer 提供后端列表,Balancer 负责监听后端列表、发起连接的创建与移除,Picker 负责在帧传输阶段从已建立好的连接 中选择一个 Balancer模块 Resolver模块 grpc服务端 解析目标名称 管理SubConn <<interface>> Resolver <<interface>> Balancer 构建解析器实例 构建平衡器实例 负责具体连接 <<interface>> Builder <<interface>> Builder <<interface>> SubConn 选择SubConn 存储 <<interface>> Picker server3 server2 server1 ② Pick grpc客户端 ① 获取连接 ③ 返还某个连接 <<interface>> ClientStream 定义grpc客户端 streaming方式 stream模块 建 立 连 接 阶 段 ④ 在选择的连接上,传输头帧、数据帧 帧 传 输 阶 段
25. POIZON 4.3 小得物流量路由 hyper Resolver grpc 解析器的作用主要有两个: 1. 解析字符串 Scheme://Authority/Endpoint 得到后端提供服务的地址列表,字符串映射的是resolver.go里的结构体Target,Scheme和 Authority不是必须的,Scheme默认是passthrough,Authority默认是空,Scheme作为key指定使用什么解析器Builder对象 2. 更新状态,触发balancer的流程,从而跟grpc服务端建立连接 内建的三种解析器: • passthrough:默认类型,用户传入的就是grpc服务端的地址 调用方法:conn, err := grpc.Dial(“localhost:50051”, grpc.WithInsecure(), grpc.WithBlock()) 等价于:conn, err := grpc.Dial(“passthrough:///localhost:50051”, grpc.WithInsecure(), grpc.WithBlock()) • dns:利用golang net包函数做域名解析获取服务端的地址 调用方法:conn, err := grpc.Dial("dns:///svc_name:default.svc.cluster.local:50051", grpc.WithInsecure(), grpc.WithBlock()) • manual:并不是通过scheme、target来获取服务端地址,而是手动维护 先创建并注册一个Resolver,再调用 InitialState 方法把服务端地址手动传给Resolver对象维护,这种类型解析器常用于测试
26. POIZON 4.3 小得物流量路由 hyper Resolver 实现自定义的解析器(Scheme命名为hyper),支持多注册中心服务发现:可从多个注册中心订阅 ServiceName 的地址变化,然后根据优 先级进行地址合并排序得出最终 addrs 更新 grpc 的 subConn 。 定义名字服务接口 注册中心优先级 配置中心里配置服 务sns-cnt-center 支持多注册中心 根据优先级进行最 支持的 Registry 类型: •nacos: 主注册中心,支持简洁服务名,如 provider:sns-cnt-center •dubbo:基于 nacos,兼容 dubbo-go 的服务名,如 CntCenterGrpc.ICntCenter •k8s:备注册中心,通过 watch endpoint 资源获取地址,pod 需要 get、list、 watch 权限,优点是不需要单独去运维 etcd 等额外中间件 •direct: 直连 url,可用于本地开发 可以通过接口扩展 registry 来支持 etcd、consul、zookeeper 等其他注册中心。 终地址计算,按照 priority 从大到小 排序,同优先级地 址去重合并,得出 优先级最高且不为 空的地址集 (priority负数表 示禁用)
27. POIZON 4.3 小得物流量路由 hyper Resolver 通过实现grpc resolver两个核心接口 Builder、Resolver 满足自定义hyper解析器逻辑,调用方式: conn, err := grpc.Dial(“hyper:///sns-cnt-center”, grpc.WithInsecure(), grpc.WithBlock()) // 以简洁服务名作key获取后端服务地址 各 Registry 的优先级可通过配置中心动态调整,配置调整后会调用 ResolveNow 更新所有 grpc client 的 SubConn 多注册中心收益:稳定性、扩展性 watch nacos watch NacosRegistry <<interface>> IRegistry DubboRegistry <<interface>> IRegistry hyper resolver 只监听小得物的nacos,生 产nacos数据同步合并到小 得物nacos(分钟级) k8s watch ark DirectRegistry <<interface>> IRegistry K8sRegistry <<interface>> IRegistry 通过远端配置动态更新 Registry优先级 更新最终地址 聚合多个Registry地址,根据 priority 合并、排序,得到优先级最高的非空 地址集作为最终地址 grpc SubConns
28. POIZON 4.3 小得物流量路由 Tag Picker grpc 每次远程调用都会创建一个ClientStream,ClientStream会调用Picker接口的Pick方法选择一个缓存的rpc链接,然后在这个链接上传输 数据。通过实现自定义TagPicker,解析预设的 tag 规则来筛选出匹配的目标地址。 ① 配置小得物环境的流量匹配规则,支持多个 规则,前面的优先匹配,后面的用作兜底 ② hyper resolver解析时会将nacos元数据设置到 resolver.Address 的 Attributes。 小得物环境服务的元数据都带有 env:xdw 标识,可用于区分生产环境的服务 ③ Pick时每个tag规则生成一个 TagPicker,分别对每个 resolver.Address 按照 Attributes 筛选,当前一个 TagPicker 筛选出的目标地址列表不为空 时,会忽略后面的 TagPicker 的结果 • 当小得物环境中有部署目标服务时,流量只会路由到小得物里的服务 • 当小得物里服务发现没找到目标服务时(即根据 env : xdw 筛选出的目标地址列表为空)会使用兜底的结果,即生产环境服务的目标地址,将 流量路由到生产环境
29. POIZON 流量路由开关 开启(前期、日常维护) 4.3 小得物流量路由 1% app.dewu.com 社区小得物环境 99% 社区生产环境 XDW DLB PRD DLB XDW APP gateway XDW APP gateway • 小得物单服务部署 • 跨环境RPC • 基础架构小流量灰度变更 • 服务调优 xdw-internal DLB 未命中去生产 SLB SLB Ingress Controller Ingress Controller Service 跨环境RPC Service
30. POIZON 流量路由开关 关闭(稳定运营期、重要节点) 4.3 小得物流量路由 1% 社区小得物环境 app.dewu.com 99% 社区生产环境 XDW DLB PRD DLB XDW APP gateway XDW APP gateway • 生产发布前置 • 混沌工程 • 大促保障 xdw-internal DLB SLB SLB Ingress Controller Ingress Controller Service Service
31. POIZON 05 未来展望:殊途同归
32. POIZON 5.1 未来展望:Proxyless Service Mesh? 什么是Proxy Service Mesh Google 的 gRPC 团队支持了 Istio 的 Control Plane,并把这种架构称之为 Proxyless Service Mesh,国内很多公司也上了类似的架构,采用 Istio 的 Control Plane 来对接 bRPC,Dubbo 等 RPC 框架。当前主流的Proxyless Service Mesh 就是 Istio 的 Control Plane + RPC 框架 xDS xDS 协议是“x Discovery Service” 的简写,这里的x表 Istio Control Plane xDS 示它是一组基于不同数据源的服务发现协议的总称,例如: • CDS:Cluster 集群发现服务 • RDS:Route 路由发现服务 Pod Pod • EDS:Endpoint 集群成员发现服务 • LDS:Listener 监听器发现服务 在 Istio 中,基于 xDS 协议提供了标准的控制面规范,并 rpc App rpc App 以此向数据面传递服务信息和治理规则。 主流Proxyless Service Mesh架构
33. POIZON 5.1 未来展望:Proxyless Service Mesh? xDS实际上定义了Service Mesh的能力标准 xDS提供了协议和标准化:既能支持envoy(sidecar形式),也能支持多语言sdk。普通的配置中心并不感知配置的实际含义,没有实现 Service Mesh的标准能力;即使RPC框架实现了Istio的所有标准能力,若没有统一的协议和配置格式,也不能算Service Mesh。 未来:重回Service Mesh? 配置中心 基于nacos2.0 Pod Pod rpc App rpc App 社区当前“配置中心 + RPC框架”并不是Proxyless Service Mesh
34. POIZON THANKS
35. POIZON 得物技术公众号

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.137.1. UTC+08:00, 2024-11-16 19:07
浙ICP备14020137号-1 $Map of visitor$