微服务-后段架构一些总结
最初的单机架构
这种单机架构并非不好,而是大部分demo的初始状态。也是最简单,最低成本的状态。
无论是服务端,还是网站,还是管理后台,数据库,都部署在一个服务器上。
多端导致的问题
- 1 网站和移动端和pc端其实很多业务逻辑相同的重复代码。
- 2 不同端的数据有时候通过数据库共享,有时候接口调用传输,这个时候接口关系很混乱。
- 3 应用会爆炸,为了提供接口逐渐的改得越来越大,归属混乱,小队成员各自为战。
- 4 管理后台如果添加了数据分析,则变得很臃肿。
- 5 数据库表结构为多个应用依赖,重构优化困难重重
- 6 几乎所有应用到在一个数据库上操作,性能瓶颈出现。
- 7 开发,维护,测试,部署越发困难,发布时带上未经测试的代码随时带来现网问题。
- 8 公共功能互相扯皮。
微服务与烟囱管
微服务改造,最关键是识别除公共的业务能力。举个例子:一个电商平台的服务可以抽象为
- 1 用户服务
- 2 商品服务
- 3 订单服务
- 4 促销服务
- 5 数据分析服务
后端应用只需要从这几个服务获取所需数据即可,所以微服务的架构会变成一个。
轻盈的前端,和一层薄薄的服务层,还有最底层的数据库层。
但是这种设计是烟囱式设计,缺点在于
- 1 数据库成为性能的瓶颈,数据库故障则全完蛋
- 2 数据库管理容易越加混乱,熵增加是万物的趋势,总有一个服务取另一个服务的数据
- 3 数据库表被多个服务依赖,牵一发动全身,演进速度指数下降
微服务与异构
数据库进行拆分,每个服务都有自己的直属的持久化层,各个服务自己负责。
而且这样的拆份带来的时候消息通信,所以类似消息队列机制,如RabbitMQ,kalfka也需要。
每个服务都可以使用异构的数据层。
比如用户服务,使用的时候关系型数据库。
商品服务,关系型数据库和缓存都可以上。
数据分析服务,可以用上数据仓库,且和ES,和Spark整合在一起
但是还是有跨服务联表查询等问题,但是依旧可以合理设计避免。
微服务的弱点,雪崩式宕机
但是微服务的最大特征就是,垮台,而且修复困难。
在以往的一台单机架构上,问题排查定位往往只需要看日志,查看整体调用栈。
但是微服务只能一个一个服务器查看日志,调用,定位。
而且服务之间的互相依赖关系也是关键,可能一个不起眼的微服务挂了,导致间接或者直接关联这个服务的服务也挂了,然后导致更多的服务挂。
这个图上的节点的关系这个节点的连通分量基本都完蛋。
所以:
- 1 微服务的定位比较难(时序问题这种史诗级别日志甚至复现问题都很困难)
- 2 稳定性下降,容易雪崩
- 3 服务数目众多,部署,管理困难
- 4 在开发进程前进的同时,还得保持服务间协同合作
- 5 端到端的测试会涉及到多个服务,测试也变得异常复杂
监控的重要性
到这一步,微服务的架构的弱点很明显,就是定位排查问题很难。
所以一个扩展灵活的监控系统是必须的,做法就是让每个服务提供一个接口,实时报告自己的状态,有点像心跳,然后搭建监控系统,这个监控系统需要一个采集器,来实时采集各个服务的状态,并且以ui的方式呈现给运维者,当到达危险临界值,甚至会发送短信和邮件给管理者和运维者,和该服务的owner。
PS:(这种采集器,UI开源社区很多)
所以本质上,监控也是一个微服务,但是不是面向业务的微服务。
链路跟踪 & 日志分析
一个请求往往涉及内部多个服务的调用,为了弄清楚内部调用之间的关系,和时间,一般使用istio trace来实现链路跟踪。
每个链路的节点,会有4个数据:
1 tranceid,2 spandi 3 parentid 4 request time&respond time
(链路跟踪的理论可见google dapper,社区也有很多开源实现如zpikin)
但是链路跟踪最后也只是定位到哪个服务有问题,并不能更细颗粒度定位
更细的只有去该服务的日志分析。
也就是ELK日志分析组件,
- 1 E代表ElasticSearch:搜索引擎,日志存储
- 2 L代表Logstash:日志采集器,接受日志,预处理输出到ElasticSearch
- 3 Kibana:ui组件,通过ElasticSearch展示数据
在每个微服务里面部署日志采集agent,把数据传输到日志采集器里去。
网关
在大量的服务,大量的接口下,容易调用不该调用的服务,本来一个只读的修改却误添加了数据,每次服务调用都应该有一层网关层进行权限校验,而且也可以作为提供接口的文档平台。
网关层可以颗粒度很细,也可以颗粒度很高。
微服务内部调用也可以设置网关,也可以不用设置。这个颗粒度就是微服务级别。
甚至可以把微服务划分为几个区,绿区是读取数据的微服务,黄区是写数据的微服务,然后区域之间有网关把控。
或者是直接最大的颗粒度,整体微服务外面就有一层网关。
服务注册与发现,动态扩容
在业务迅速扩展的时期,或者是遇到某些特殊时段,需要从4个服务实例,增加到40个服务实例。需要实时扩容和调整。
- 1 新增实例
- 2 将新增的实例注册到负载均衡或DNS上
但是也有更加聪明的做法,那就是弄出一个服务自动注册和发现的机制(注册发现微服务)
一个新增的实例服务,启动部署之初就会把自己注册到发现微服务上。
这个发现微服务,一方面做负载均衡的工作,另一方面会定时检查不健康的实例,去掉他们。
甚至可以在注册服务的时候,加入一些元数据,服务版本,做A/B Test等等。
一般用一个redis就可以轻松实现,或者使用服务发现组件,zookeeper,eureka,consul,etcd
service-mesh, serviceless,FasS,PasS,IasS
基于以上这些内容,一套完整的微服务框架,需要指标接口,链路跟踪注入,日志引流,服务注册发现,路由规则组件,熔断限流降级等功能。如果让每个微服务都自己实现这一整套不科学。
需要抽取这些公共能力出来,然后每个微服务都需要按照这个公关能力的协议,进行开发。
但是使用统一的微服务框架,升级成本很高,如果已有数百种微服务在线,那么升级一次所有都跟着升级。
但是如果把这些公共能力都抽象到一个反向代理的组件,每个微服务都部署这样的一个代理组件,进行处理转发,这样的组件称作 sidecar,这里负责网络通信的部分叫数据平面,负责管理的叫空指平面,从而一起构成了service mesh的基本架构。
- IasS 这种就是腾讯云,亚麻云这样的云服务器提供商。
- Google App Engine就是PasS
- AWS Lambda就是FasS
打个比喻,IasS是买车,PasS是租车,FasS是打车。