35

高并发、高可用架构系列(一):手把手带你构建大规模分布式服务

 4 years ago
source link: https://mp.weixin.qq.com/s/rT6s6VkU_tyMFCpSPpvnTQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

vYbURj2.jpg!web

作者: 丁浪,目前在创业公司担任高级技术架构师。曾就职于阿里巴巴大文娱和蚂蚁金服。具有丰富的稳定性保障,全链路性能优化的经验。架构师社区特邀嘉宾!

阅读本(系列)文章,你将会收获:

  1. 全面、体系化的了解大规模分布式系统中的服务治理  

  2. 一线互联网公司如何应对高并发、大流量场景,稳定性保障体系揭秘(高并发高可用必备)  

  3. 常见限流算法的实现,阿里巴巴(历年双十一)限流、熔断保护利器sentinel的设计原理和实践经验(高并发高可用必备)  

  4. 高性能、高可用配置中心的本质、架构设计思想、原理和实践经验(微服务架构必备)  

  5. 高性能、高可用服务注册中心的本质、架构设计思想、原理和实践经验(微服务架构必备)  

  6. 互联网公司技术架构的普遍痛点、架构愿景及解法(技术广度和思维能力)  

当我们在谈论“服务治理”的时候,都在谈论些什么?

我从业之初接触到的便是一堆基于Webservice、Hessain等实现的跨语言的分布式系统,那是SOA架构和理念十分盛行的时代,我常常听到前辈们在谈论 “SOA治理” 等高大上的词,但我当时并没有理解何为 “治理” ,甚至在想:为什么不叫 “管理”呢?在此之前,我仅在小学课本上接触过 “污水治理”这个词。直到近些年互联网企业大规模服务化进程的推进,以Dubbo、Spring Cloud为代表的开源服务框架流行起来, “服务治理” 又热门了起来。

fQBBjyI.jpg!web

那到底何为 “治理” 呢?大型互联网公司动辄几千上万个应用,而中型公司也至少几百上千个应用。微服务流行后,服务数量更是与日俱增, 亟需治理 。根本原因还是 复杂度过高,需要梳理起来、规范并优化架构的本质就是管理复杂度,满足不同利益相关者的诉求 。下面我将简单的总结下 “服务治理” 领域的各个方面(包括但不限于), 便于你建立全面、体系化的理解和认识,以便进一步深入研究和实践

服务定义及管理

服务该如何定义,又该以何种形式暴露出来,上游需要怎么调用,拆分粒度怎么把握…这些都需要统一的规范和约束,否则组织协作很容易乱套。我曾经听到某位架构师讲“微服务就是一个接口一个服务…”,也曾接手过类似的系统,这是典型的 “技术理论派”,永远掌握不了技术或方法论的本质。

再比如我们在开发某项业务功能时发现需要依赖其他域的支持,这就需要了解公司某个子域、某个应用中包含了哪些服务,有没有提供我们想要的业务能力,以及进一步了解服务契约描述长什么样的,这样我们可以快速接入,这就需要好的管理机制和平台支撑。如果是一家创业公司,只有数十个应用系统或者服务,只有20个技术人员,则不会面临类似复杂度,面对面的喊一嗓子就可以了。

但是, 最基本的规范和约束在任何规模的团队都是必须的 ,这里分享些常识经验,例如:接口定义中参数不要使用Map类型,过于灵活的结构往往会导致接口契约定义不清晰,消费方难以理解,而提供方的代码逻辑也将充斥各种判断和特殊处理;响应结果DTO定义中不要使用枚举,因为如果服务提供者新增了枚举值而服务消费方未升级二方包,是很容易导致反序列化失败,这个在阿里时期曾目睹过类似线上事故;只允许新增接口,不允许修改现有接口的定义,除非你能够确保上游消费者全部统一升级,这个在稍微正常点的公司显然都是不可能实现的;

别看我列举的这些问题好像都很初级,但是很多公司这方面做的确实都很烂,否则技术圈就不会有那么多 “前人挖坑,后人填坑” 的故事了

服务的注册与发现

服务提供者如何 将服务注册上去 ,消费者端如何快速 发现服务、挑选服务 ,是这个领域要解决的核心问题。开源的注册中心如何选择?注册中心的容量够不够?服务提供者线下后,注册中心能否及时感知并通知消费者?选开源还是自研?这些都是架构师需要考虑的问题。

关于服务注册和发现这里面又会涉及到网络通信,负载均衡,健康检查,数据存储,分布式选举算法和协议等,后面我会有单独的章节仔细展开讲解

MVjYVrF.png!web

服务的调用、路由、容错

服务调用,从通信协议上可以选择TCP/UDP,或者应用层的HTTP协议。从风格上主要有二进制RPC的,或者HTTP+JSON的(这里我纠正一下很多技术人员的认知误区,很多公司所谓的 “Restful”服务其实就是提供的HTTP接口而已。就像很多人口子的 “H5”其实就是一个适配手机屏幕尺寸的小页面,根本没有任何HTML5的新特性)。以RPC框架为例,从编解码层面又会有自定义的私有协议。再往上到应用层又会有序列化和反序列化,采用protobuf序列化还是才是Hessaion2,需要从性能、兼容性、稳定性、跨语言、可读性、可测试性等方面综合考虑

服务路由,这个也很容易理解,比如开源的Dubbo框架中提供的分组管理,这可以理解为是一种路由。HSF中提供的 “同机房优先”能力,这也是一种路由策略。我们有时候需要对服务实现 “黑名单、白名单” 的过滤保护机制,这就是一种按条件路由。我们在做一些类似 “灰度发布、流量染色、环境隔离” 等的时候都需要使用到特殊标记然后透传,在服务调用时按规则做路由。当然,更重要的是注册中心的模型设计足够灵活,可以支持类似打tag区分的能力。对于外部的服务而言,我们通过借助网关、Nginx等来实现路由(这种本质上就是请求转发)

服务安全,几乎所有的系统而言通常都需要做身份验证,权限校验等。在分布式微服务架构中,通常我们会将鉴权等横切操作放到网关中,外部应用想要访问服务需要先经过网关,比较通用的就是借助Oath2协议、JWT组件等来实现。而对于内部服务间的调用,因为都是在内网中,会有防火墙等安全手段,基于性能、工作量的考虑,很多公司不会再单独做鉴权。当然,必要的水平权限校验这些还是很有必要的。另外,在流量接入前通常会设有WAF(web应用防火墙)过滤恶意请求。比较常见的安全问题包括:XSS、SQL注入、DDOS、水平权限等,这里不再继续展开

服务容错模式很多,常见的大概有如下几种:

failfast,快速失败,比如在Java集合框架中当并发对ArrayList等容器做修改、移除等操作时系统就会抛出ConcurrentModificationException异常,这就是典型的failfast机制。在分布式服务调用中,最常用的failfast机制就是超时,无论是服务提供者还是服务调用者,都需要设置超时;  

failover,失效转移,在分布式服务调用中会偶发网络抖动等问题,通常我们会选择另外一台机器进行重试,这就是典型的failover。另外,在数据库、消息中间件领域中,经常会使用类似Master、Slave的架构模型,当发生故障会自动执行主从切换来保障集群的高可用;  

failback,失效自动恢复,当请求发生异常或失败时,应该能够保留上下文信息,通过某种机制让其自动重试。比较典型的实现方式就是捕获异常状态,记录日志或者落到 “异常恢复表”中,再通过后台定时任务扫描执行补偿。通常适合对数据时效性、一致性不太敏感的场景;    

failsafe,失败安全,当请求发生异常或失败时,简单记录日志后直接忽略,继续推进主流程。比较适合一些非主链路、弱依赖的请求,例如:上报操作日志给大数据平台;

依赖治理

先灵魂拷问下,我的服务被哪些应用依赖了?上游调用量太大会不会把我拖垮?我挂掉了会不会导致上游发生故障?我自己又依赖了哪些服务?他们挂了会不会影响我?哪些是强依赖哪些是弱依赖?这些问题都是需要了然于心的, 依赖治理的本质就是管理复杂度,规避或降低风险

服务监控和应急手段

服务监控,主要包括: 日志监控、调用链跟踪、度量指标 这几块构成,其中的每一块都是一个非常值得深入研究的领域。在云原生时代,我们将其统称为 “可观察性”

大型分布式系统通常由成百上千的应用组成,机器数量也是动辄上千台,是不可能像很早以前一样ssh登录到服务器去执行tail、less的。我们首先需要日志格式统一,日志路径统一,然后对日志进行 采集、上报、快速分析、展示和预警 。在这个领域,开源社区最流行的代表作是ELK;

前面讲 “依赖治理”的时候已经了解到分布式系统间依赖的复杂性,调用链错综复杂,已经不可能依赖个人经验了。当发生故障或者性能问题的时候,我们需要能够 “一目了然”、“顺藤摸瓜” ,从而达到 快速定位故障或者性能瓶颈 的目的。在这个领域的代表作有:pinpoint、cat、skywalking、淘宝鹰眼等以及一些商业化APM;

从应用视角,我们需要了解服务的 调用量、成功率/错误率、响应时间等指标 。同时,我们也关注 线程池、慢查询、连接数 等等。从业务方视角,我们需要关注**“当前订单数” 、 “下单总金额” **等类似的业务指标数据。这些指标数据都是跟 时间维度 相关的,我们需要将这些指标数据保存到时序数据库中,做聚合统计、排名然后展示或者预警;

IfMvQfq.jpg!web

限流,主要包括:页面限流、接口限流,访问来源或IP限流、单机限流、集群限流、网关限流、热点参数限流,自定义限流等;北京地铁口早晚高峰期的控制,就是典型的 “限流”(通常分 “匀速排队” 和“快速失败”);

降级,从触发条件上可分为:手动降级和自动降级。从场景上又可以分为:一致性降级、完整性降级、用户体验降级、读写降级等;电商在高峰期资源紧张时关闭商品评论服务和推荐服务,这就是一种典型的 “弃车保帅”的降级手段。此外,接口的自动熔断也是一种典型的降级手段;

关于依赖治理、容量规划、限流,降级等后面我会在后续稳定性保障体系的章节中展开仔细讲解

服务测试

服务发布上去之后怎么知道是不是OK的?如果有一个ops控制台,我可以选择服务后直接输入参数、轻松点击就能验证服务通畅是不是很爽?如果在开发联调,或者进行单元测试时,对方没有实现,双方只是确定了服务契约,那我们就需要可以轻松mock数据。在传统的测试体系中,我们通常分为:单元测试、集成测试、组件测试、端到端测试等,形成了经典的 “测试金字塔模型”。

ieINveR.png!web

到了微服务时代,我们在 “集成测试”时不同服务间的调用便成为了重点,于是引入了 “契约测试”来保证服务提供者和消费者双方符合规范

小结

从架构师的视角看服务治理,需要关注开发、测试、运维、业务方等(利益相关者)各方的诉求,在技术选型和架构设计时需要 权衡取舍 ,尽可能满足他们的诉求,如图:

BrIZJbu.jpg!web

后续章节

高并发场景下的常见问题及稳定性保障体系

阿里巴巴双11利器sentinel的设计原理和实践经验

高性能配置中心的原理和实践经验

服务注册中心的原理和实践经验

会陆续更新,如有收获,请点个在看,您一在看,我就更新的更来劲儿了!

长按订阅更多精彩▼

rEFzyej.jpg!web

如有收获,点个在看,诚挚感谢


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK