单体应用已经无法适用于云的高可用、可扩展的特性,对于互联网应用来说,将传统的单体应用进行微服务化改造后并上云(不论是私有云还是公有云),就成为了迁移到云原生应用方案的不二之选。
微服务的这个词出现已经有几年了,随之产生的组件也有不少,微服务可以抽离出那些大家都会关注的问题,并将它们进行组件化,很多组件聚合到一起就行成了一套微服务框架,目前比较成熟的微服务框架和机构有很多,比如:Spring Cloud, CNCF等。那么微服务框架当中都有那些组件呢?下面展示一张图来让大家有一个整体的认识。
1.服务网关
将后端的多个服务变成黑盒,对外只暴露唯一的服务网关,网关根据路由配置将外面访问的请求转发到具体的某一个服务上。一些成熟的网关组件其实除了路由功能以外,还集成了诸如,权限验证,服务注册/发现/负载均衡,熔断,限流和降级的功能。
2.权限验证
若想要请求后端的微服务,需要对请求进行相应验证,第一次访问时根据相应的授权凭证(例如:用户名/密码),到授权服务那里进行权限鉴定,若鉴定成功,根据相应的加盐加密算法会生成一个Token串,下次请求再来时需要携带此Token串,授权服务会对Token串进行解密校验,该Token串是唯一的,并且可以标识用户的身份以及存储一些profile信息。
3.服务注册/发现/负载均衡
每个微服务启动需要到注册中心那里去注册自己,将自己的地址以及服务名告诉注册中心,若要实现基于性能的负载均衡,同时还要上传自己的CPU,内存等信息给注册中心。当需要消费服务时需要先到注册中心那里根据服务名来获取提供服务的服务地址。每个服务一般会注册多个实例,一般会根据一些策略(wrr,round robin等)来挑选具体某一个服务实例,注册中心需服务实例会保持着心跳机制,若服务实例挂掉就会从注册中心消失,因为注册中心没有继续收到服务传过来的心跳信息,则会判定该服务死亡,那么就会从服务列表中将其删除。
4.限流/熔断/降级
熔断其实类似日常生活中的“保险丝”,一个用户请求的调用,在微服务内部可能是多个服务之间的连环调用,若其中一个或几个服务产生了系统瓶颈,就会导致超时,这样会阻碍整体调用链的调用进度,从而导致整个系统连接数过多,造成系统瘫痪,那么熔断要做的就是当发现某一服务的错误、超时、负载,达到某一指标时候来拦截后续的请求。当服务产生熔断后,那么就需要对服务进行降级,降级可以立即给用户一个返回,及时的返回空白内容或是错误信息。顾名思义限流就是限制请求的qps,将请求的数量控制在该服务可以接受的范围内。
5.消息中心
它在微服务中起到了很多作用,利用消息的订阅发布可以解决分布式最终一致性的问题,而且也可以实现服务之间的异步调用,让服务与服务之间进行解耦。
6.分布式跟踪
分布式微服务中,对外暴露的用户请求,在微服务内部可能会是服务之间互相调用多次的结果,某一个请求超时或出现错误,我们都需要了如指掌。目前一些开源组件也有很好的实现,主要就是根据链表的数据结构,对整个调用链进行唯一的TraceID标识,每个调用节点也有自己的SpanID和上一个调用节点的ParentID,ParentID为Null时就是起始调用节点。每个节点会存储相应的信息,包括客户端发起请求时间,服务端收到请求的时间等等。默认这些信息都会存入内存中,也可进行数据持久化,然后通过WebUI查看整个调用链的详细信息,便于分析。
7.REST/RPC/序列化
微服务中,无论是对外暴露的接口,还是服务之间互相调用的接口,都离不开通讯协议与序列化。通讯协议有我们所熟知的http, soap, websocket,rpc等,序列化有json,xml,protobuf,bytes,text等。对外提供服务的接口一般都会使用http+json的方式,服务内部之间调用的话通常会使用rpc+prtobuf的方式,rcp是二进制的,它比http传输性能要高,而且protobuf的序列化/反序列化性能同样比json的要高,http是可以跨语言的,没有语言的约束,但rpc对语言是有一定约束的,虽然如此但目前有很多成熟的rpc框架以样也可以实现跨语言。
8.统一配置管理
微服务自然会有很多个小服务,若每个服务都有自己的一些配置,那么运维起来简直就是噩梦,所以统一的配置管理是必要的,目前有一些成熟的开源的框架都可以做到,有了配置中心,我们就可以根据不同环境应用不同的配置,多种配置都可以存到git中,进行版本控制,根据路径规则匹配不用的配置。同样也可以支持热更新,无需重启服务。
9.CI/CD
持续集成与持续交付,快速的迭代是微服务所需的,服务多了本来就复杂,而且服务之间的接口变更和新功能的添加都会比较容易造成互相制约,若不采用持续集成与交付的话,那项目进度就会被拉的很长,目前CI/CD比较好的实现方式就是,git + jenkins + docker, git负责源码版本控制,jenkins进行自动化的打包,编译,测试,部署,这里部署我们可以使用docker容器,也可以不使用,直接放到物理机上运行,主要还是看项目的底层架构
10.日志
分布式的微服务,每个服务都会产生日志,那么当要分析问题时我们肯定不会每台机器的去查看日志,这也会是一场噩梦,好的办法就是收集聚合所有服务的日志,然后汇总到一起,根据服务名,TraceID,IP等一些关键字进行过滤来找出有用的日志。ELK就是解决此类日志问题的利器。
11.监控
单点应用定位问题相对来说是比较好定位的,但是服务多了,微服务之间互相的接口交互,哪个节点出现了问题都需要快速定位到出现问题的点,若微服务运行在容器当中,我们同样要考虑容器的监控,以及app的日志监控,同样还有app的业务监控。
以上已经把微服务的大部分功能模块做了一个简明扼要的阐述,那么下面我们就来仔细聊聊微服务的监控。
对于微服务系统来说,相对比较复杂的是监控,容器编排,还有日志收集,容器编排目前有很好的实现,比如Kubernetes, Swarm, Mesos,等等,这些都解决了容器的编排问题,这里之所以提到容器编排,是因为微服务的落地比较好的实现方式就是运行在容器当中,多亏了这些开源组件的存在,很多微服务所要考虑的问题都被集成到这些平台中了。那么对于这种多说上千万个虚拟容器的大集群来说,监控到底怎么实现呢?
基于容器的微服务监控大致可以分为,容器与宿主机的监控(基础监控),API监控,调用链监控以及应用本身的监控,那么接下来就简单的说一下这几种方案。
1. 容器与宿主机的监控
基于容器的微服务监控和原始的监控是有很大区别的,因为服务的实例生存周期很短,分分钟可能就会有容器的生灭。微服务的容器与宿主机的监控离不开CPU,内存,磁盘,网卡这些基础的性能指标,对于宿主机的监控来说,我们可以依然使用原始的监控方式,每个宿主机安装一个代理来采集服务器的性能指标,代理在采集性能指标的时候可以打上时间戳和相应的标签来区分不同性能指标的数据维度(metric),然后将监控数据汇总到时间序列数据库,里面的数据可以对接目前一些开源的组件来进行可视化的展示,也可以对接报警服务(结合报警服务的报警策略)进行报警。容器的监控自然就和宿主机不太一样了,我们不能说给每个容器镜像内部都集成一个监控代理(agent),这样的话侵入性太强, 不易于维护。目前有比较成熟的开源产品Prometheus,它有很多的Exporter可以用来采集监控数据,例如我们想采集Kubernetes上所有容器(pod)的性能指标的话,Promethus可以通过直接配置多个Kubernetes ApiServer的Endpoints来监控整个Kubernetes集群。
2.API监控
微服务对外暴露的api都是经过服务网关来访问的,那么我们可以在网关上对这些api进行流量的分析与监控,监控api的访问量,api的响应体状态码,当某些指标达到阀值时我们就可以进行报警,目前也有很多开源的产品可以使用,例如Kong,它可以安装很多功能性插件,其中就有dashboard插件,以及监控插件。
3.调用链监控
有了对整个微服务调用链的监控,我们就会有一种一览全局的感觉,对整个微服务集群的部署情况,以及运行情况了如指掌,可以很快的定位问题,协同开发人员进行性能调优,量化运维部门的价值。目前有谷歌的Google Dapper但是没有开源只有论文,Zipkin, OpenTracing,这些都是根据谷歌的论文开发的开源产品都很不错。
4.应用本身的监控
微服务应用本身的监控的方式就比较多样了。这里我就说一下我自己基于Kubernetes实现的微服务应用级的监控插件,先上个图:
在Kubernetes的master节点,也就是安装apiserver的那台服务器上运行一个监控插件,该插件可以通过一个kubernetes提供的官方客户端来访问apiserver,首先我们要告知插件要监控哪个namespace下的哪个service,然后,插件通过和apiserver进行交互获取某个service下所有Pods的实例,插件会并发访问所有pod提供的/metrics接口(Path可配),并给每个pod的返回数据(json格式,遵守一定的数据格式契约)打上pod_name的标签来标识每个pod返回的metrics,打上pod_name标签的同时也会打上service_name的标签用来区分具体是哪个service的监控数据。通过插件收集整理后的数据会上传到时间序列数据库中,后续就可以根据数据进行可视化分析以及展示(Granfana),同样若是结合开源监控Prometheus, OWL也可以实现监控报警,只不过结合不同的监控需要返回它们所需要的监控数据格式罢了。
微服务目前也是在如火如荼的发展着,随之产生的技术栈和开源组件也是百花齐放,到底什么样的方式和组件是最适合的,这些都是仁者见仁,智者见智。技术无好坏,用的顺手合适就可以,解决相应的问题用合适的方法和武器,知己知彼,不一定所以的问题都要使用微服务来解决,杀鸡焉用宰牛刀。以上是鄙人的一些拙见,阅读了一些技术性文章和书籍加上自己的一些理解所总结,希望能给那些还没有走进以及即将走进微服务的人带来一丝启发。