如何分析基于容器的微服务架构技术选型与设计
如何分析基于容器的微服务架构技术选型与设计,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
背景介绍
作为金融企业,国投瑞银基金多年以来 IT 工作主要还是以运维为主,主要业务系统基本采用外购模式,但随着业务的不断发展,业务部门个性化需求越积越多,外购与外包已经不能很好满足业务员部门的需要了。2016 年底公司着手开发团队的组建工作,同时对公司的业务开发平台进行架构选型与设计,以求统一开发平台,提升研发效率,从而加快业务部门的业务需求处理效率。
下面我们将就这两年在平台架构选型、平台架构设计、平台及相关子系统的逐步完善背后的一些经验进行分享。
适用对象
该架构全部基于开源平台,经过三年多的生产上线实践,平台运行平稳,可扩展性强,可用性高,可以很好满足公司对于金融业务不断发展的需要,这对类似的中小型企业的业务架构选型也具有一定的参考意义。
注:UFOS:国投瑞银基金运营系统
架构设计与选型
架构设计考量因素
在初期平台架构设计与选型时,我们根据现有业务系统的需求,梳理出了技术架构选型需要考量关键因素:
架构平台的前瞻性或先进性,符合当前潮流与未来发展趋势,有较好的生态链和较强的生命力,不能因为平台架构选型不当,导致未来平台重新架构,造成大量的迁移和重构工作,需保障平台架构能在一段时间内保持技术领先。
这里有两点注意,一是对技术成熟度的考量,是否采用有风险的前沿技术以及拥抱这种技术带来的风险,这一点类似于金融投资中收益与风险的关系,我们需要在系统的先进性与系统的稳定性之间进行平衡;二是采用前沿技术可能会面对更多的困难,如国内可能缺乏相关资料,或难以找到可以参考的成功案例,很多时候只能通过官方和论坛获取相关技术信息,会对架构按时交付带来风险。
平台的可扩展性
能满足基金行业业务不断的发展与创新的需求,尽量能做到平台的横向平滑扩展,满足以上特性其实就决定了架构的分布式特性,当然我们更希望它是云原生的架构
系统的可靠性和可用性
作为金融业务系统平台,需保证业务系统连续不间断运行,保证平台的高可用。采用集群或平台自动恢复功能,确保平台局部出错也不影响系统整体的运行;这里有两个层面,一是业务系统中的功能组件能相互隔离,其中一个组件的不可用不能影响到系统的其他部分;二是平台基础系统采用集群架构,有自动恢复功能,确保即使系统中有节点出错,也可在很短时间内完成出错节点中服务的切换与恢复
开销
不同的架构 / 技术选择有着不同的开发成本,包括技术框架,平台的学习成本,我们期望平台能支持异构的技术,使得开发人员可以采用比较适合的技术栈来快速实现业务功能的开发
开发运维一体化思想( DevOps ),在设计时考虑运维,尽量减少后期运维操作的复杂度,减轻后期业务系统运维的负担。
让开发人员更多专注在业务功能需求开发,其它非功能需求如负载均衡、高可用等尽量由平台提供,做到对开发人员透明,以提升开发效率。
当公司规模不大,实力不足以自己实现部分或全部架构,选择现成的"轮子"来组装自己的架构就成了一种自然的选择。在选择上可能会更多考虑如何使用更"标准"的"轮子"来满足自己业务的需求,以便于今后业务的升级和扩展。
要实现上述平台的扩展性和高可用性,一般都离不开分布式架构,而分布式架构一般离不开服务来承载 。
基于服务架构演进
基于服务的架构设计早已有之,比如基于 RPC 的服务调用,最早可追溯到 CORBA,以及现在还有很多金融公司在交易系统中使用的 BEA 早期的框架 Tuxedo(主要编程语言为 C/C++)。后来者有 Facebook 的 Thrift,Google Protocolbuf 框架 /grpc,阿里的 Dubbo 框架等等。这些框架支持消息的二进制编码(序列化与反序列化),效率高,因此成了对网络传输,并发处理要求高的应用如 App 应用,游戏,交易软件等的首选。
后来随着 HTTP 协议的广泛应用,发展衍生出面向服务的架构(SOA)的架构设计,该架构一般都应用在比较复杂,大型项目中,为了异构系统中的功能复用,或系统性能的考量将功能模块独立出来成为服务,服务可以分布式部署,服务之间通过标准的软件接口方式在网络中相互调用;为了统一服务调用标准,SOA 往往还引入了数据总线概念,服务可以通过数据总线进行服务注册,服务的查找与调度。
SOA 架构中的服务之间是松耦合的,服务的颗粒度相对比较粗,而近些年出现的微服务,则可以看作是对 SOA 服务的一种精简,细化,或者说是 SOA 服务的轻量版。
微服务
在谈及微服务的时候,大都会对应到单体应用,以示鲜明对比;单体应用其实就是一个服务中包含了太多种功能的应用,它跟面向对象的设计里的单体类(包含太多功能实现的类)的提法颇有些类似,英文单词中有一个专有名词 monolithic 来描述二者:
如果你再仔细对照微服务和类,你会发现两者有诸多相似之处,比如微服务和类在设计原则上也是一致的,也就是高内聚 / 封装与松耦合,高内聚也就是只负责一项任务,也就是单一职责原则,而松耦合则是指模块之间的接口尽量简单,减少耦合度,这样也使得开发,独立部署和升级微服务更加容易。
HTTP 反向代理 / 服务网关
微服务除了内部相互之间调用和通信之外,最终要以某种方式暴露出去,才能让外界系统(例如 Web 应用、移动应用等)访问到,这就涉及服务的前端路由,它是连接内部微服务和外部应用系统的一个通道。
HaProxy 与 Ngix 等工具也可以实现 HTTP 反向代理,但基于以下特性,开源的 HTTP 反向代理与负载均衡工具 Traefik 成为我们的最终选择:
Traefik 更适合需要服务发现和服务注册的应用场景,它 支持多种后台应用自动发现,如 Docker,Swarm,Kubernetes,Consul 等,它还可以动态监测后台服务的变动以自动实时更新自己的配置。
支持限流与自动熔断功能。
支持配置热更新。
可以说 Traefik 非常适合容器化的微服务,采用 Traefik 可以带来以下好处:
服务反向路由,Traefik 将外部请求反向路由到内部具体的微服务,这样虽然系统平台内部是复杂的分布式微服务架构,但是外部系统从代理上看到的就像是一个统一的完整服务,代理屏蔽了后台服务的复杂性(类似 Facade 模式),同时也可以屏蔽后台服务的升级和变化。
便于安全控制,服务通过代理统一访问后端的微服务,而代理访问微服务是通过容器内部网络进行,也就是微服务都可以不用暴露端口到容器外端,外部应用也就不能直接访问容器里边的微服务了,而必须通过 Traefik 代理。代理有微服务的注册信息,它可以根据微服务名正确路由到相应的 IP/ 端口的微服务容器。这样我们的安全策略就只需要集中在 Traefik 代理端控制即可。
提供多种格式度量数据,比如可以提供我们采用的 Prometheus 监控数据格式,提供访问量,调用延迟,错误计数等数据,为后端的性能优化或者扩容提供数据支持。
在我们的架构选型中,我们选择了流行的开源框架 ELK 栈;日志写入远端的 Elasticsearch,通常可以采用两种方式,一种方式是通过日志代理,如 Elasticsearch 提供的高效的 Beats 工具,可以将 Beats 与业务服务部署在一起,这适合第三方服务(没有源码)或开发语言无标准日志组件的服务。而另外一种方式则是通过日志的 SocketAppender,直接将日志通过网络写入远程的日志服务,如 LogStash,很多标准的日志组件都支持这种方式,如 Java 标准日志输出如 Log4j,Logback 等。这种方式也比较适合在容器中部署的微服务,不需要额外再部署另外的日志工具。在我们微服务平台中,日志输出我们选用了性能较高的 Logback,并选用了与之配套的 LogStash 输出插件,通过该插件(代理)Logback 可以将日志通过 Socket 直接输出到 Logstash 服务,而这毋须对代码做任何改动,仅需要通过简单的配置文件配置即可方便实现,对调用日志的应用微服务完全透明。
为便于后续的日志查找和 Kibana 中的日志数据展示 我们需要对日志的格式进行规范化,以便将日志中的关键信息以键值对的方式存入 ElasticSearch,规范化涉及到日志文本的编码与解码,分别在应用端和 LogStash 端,LogStash 服务可以通过配置来对消息进行 Mapping 和过滤。
如果日志量比较大,则需要在日志输出与 LogStash 中间增加消息缓冲,Kafka 是一个高吞吐量的消息系统,Log4j2 有直接输出到 Kafka 的 Appender。
监控子系统
监控系统是平台服务治理中的一个重要组成部分,没有监控的应用系统可以称作一个裸奔的系统;我们原有的业务平台已经有了一套传统的监控系统 Netgain,但更多是对基础设施的监控,缺乏对应用系统内部状态的真正监控,比如对微服务和容器的支持,不能很好满足 UFOS 微服务平台的需求。
Prometheus 作为从 CNCF 毕业的第二个开源项目(第一个是容器编排项目 Kurbernetes,Prometheus 本来也是源自 Google 对 Kurbernetes 的监控),它能很好地监控服务以及容器,除了能与 Kurbernetes 无缝集成以外,也可以与 Swarm 很好地集成,尤其是配合 Docker Swarm 中的 label 与 global 配置选项使用,可以非常方便实施远程应用监控代理(exporter)的部署。
由于 Prometheus 是一个开放的监控平台,因此有大量的官方及第三方的监控代理 Exporter(监控代理可以协助不支持 Prometheus 数据采集接口的第三方服务公开自身的监控数据),在 UFOS 中主要使用了以下监控 / 代理:
Prometheus 提供多种客户端 API 接口调用库,如官方提供 Java,Python,Go,第三方提供 C++,PHP 等库,通过这些库你可以很方便在你的微服务中植入监控的度量数据(通过微服务 Web 接口,如果是批处理任务,则可以将生成的监控度量数据发送到 PushGateway 服务进行托管),为 Prometheus 服务进程拉取到,这样我们可以方便实现对业务数据的监控。
监控界面展示使用 Grafana,Grafana 是一个开源的图表可视化系统,支持多种时序数据库如 InfluxDB,当然也支持 Prometheus,Grafana 有丰富的图形展示组件,官方网站也提供大量现成的模板,UFOS 中对 Swarm 节点,微服务,数据库,告警等资源进行了监控展示。
高可用设计
为保障业务的稳定可用,平台应保证持续可用,不会无故宕机,即使出现故障也可以快速发现和定位,通过监控机制,能在系统用户发现之前尽快解决问题,抑或系统能通过设计自动发现故障并进行自动故障转移,比如通过主备或集群的冗余方式来避免单点的问题,这里我们将针对后者,从系统设计来提升系统高可用性进行简要介绍。
接入层
UFOS 运行平台基于 Linux 系统,平台入口是 HTTP 反向代理 Traefik,为实现入口的高可用,我们必须保证 Traefik 的冗余备份。
Traefik 本身支持集群方式的 HA 方式,基于配置的 K/V 存储,官方推荐的是 Consul。但是由于我们服务平台是基于 Swarm 集群,Traefik 是以 Swarm 服务方式运行(限制在 Swarm Manager 节点),它可以通过 Swarm Manager 节点读取到足够的 Swarm 中运行的服务实例的相关信息。而 Swarm Manger 之间通过 Raft 算法实时交换信息,因此运行多个独立的 Traefik 实例它们获的服务实例信息是最新也是对等的,所以我们并不需要按官方指引的使用 K/V 存储来实现 Traefik 的高可用。
为实现 Traefik 的故障自动转移,我们对运行 Traefik Replica 实例的 Swarm Manager 节点设计了基于 VIP 的 Linux 集群方案,使用 Pacemaker+Corosync,其中 Corosync 用于检测节点间通讯是否正常,而 pacemaker 则用于管理集群资源。当检测到 Linux 集群中的任何一台节点故障时 VIP 会自动切换到其他的正常节点,入口也自动切换到该节点上运行的 Traefik 上来,保证 HTTP 访问代理的可用。
应用服务层
所有的微服务都是以 Swarm 服务的方式运行在 Swarm 容器平台上,微服务的高可用性由 Swarm 提供。Swarm 容器编排系统本身支持高可用,在 UFOS Swarm 集群中配置了三台 Manager 节点(最多可以承受一台 Manager 故障),Manager 之间通过 Raft 进行 Leader 的选举,这种选举保证了单个节点的异常不影响整个 Swarm 集群的运行。
Swarm 中运行的微服务容器也是高可用的,一是可以通过启动多个相同微服务实例来实现微服务的高可用,Swarm 内部可以通过 VIP 的方式来实现微服务容器之间的负载均衡与故障的无缝切换(VIP 只会转发到健康的服务)。即使是单个微服务容器实例,Swarm 仍能保证微服务的高可用性,如因节点故障,导致节点中运行的微服务容器异常,Swarm Manager 可以自动检测到节点异常,然后把异常节点中的微服务容器,转移到集群中其他健康的节点上去,并在其他节点重启微服务应用,这样仍然可以保证容器中运行的微服务可以被访问,从而实现微服务的高可用性(容器编排技术可以保证容器的动态发现,即使容器被转移到其他节点上重启,从而实现微服务的动态访问,当然这里可能有个延迟,要实现这点还有一个就是需要保证微服务被设计为无状态的)。
数据层
Oracle Database 采用典范的 RAC 集群,MongoDB 则是基于官方提供的容器镜像,以容器方式实现了三台 MongoDB 的 Replica 配置。
Redis 采用主从复制模式,配置了一主二从三个节点,同时配置了相等数目的 Redis Sentinel,这些 Sentinel 能共同合作完成故障发现与判断,以及故障转移,并通知应用方,从而实现真正的高可用。
ActiveMQ 采用官方推荐方式,实现了基于 RDBMS 的主从模式,从消息队列定时从 RDBMS 共享表中检测主消息队列的刷新情况,如主消息队列异常,未能在指定时间内更新,从消息队列提升自己为主消息队列,从而实现主从的切换。这里需要注意的是必须保证主从服务节点的系统时间的同步。
文件系统的高可用是通过 NFS 文件系统与底层的存储来实现。
经过生产环境的实践,随着平台的不断完善和运维经验的不断积累,UFOS 平台的可用性已从 99.95% 逐步提升到了 99.99%。
该基于容器的微服务架构平台给我们的研发带来了以下益处:
经过三年多微服务平台运营实践,总结起来该基于容器的微服务架构平台给我们的研发带来以下益处:
由于完全基于开源系统,可以实现自主可控
平台基本对于开发人员来说透明,同时 DevOps 使得运维简单,有效提升了研发效率,节省了人力资源方面的投入
平台微服务开发语言选择更具弹性,现在平台中已有三种语言开发的微服务,而且平台还可以根据开发语言的发展进行语言的更迭,也可以根据市场的变化对开发语言进行调整,最大限度保护现有投资,以及最佳化未来投入
实现公司的统一开发服务云平台,可以无缝整合现存的第三方服务商提供的服务,有效利用平台在服务治理方面的资源
可以方便整合第三方开源软件系统为平台直接使用,为平台提供服务,有效节省开发人力投入
容器运行环境高度统一,微服务问题可以排除干扰,便于问题分析与排查
该架构平台运行非常稳定,可用性高,可扩展性强,可以根据业务需要进行动态扩展,可以满足公司业务的未来长期发展的需要,并且技术架构有一定的前瞻性,有效避免了因平台架构选型不当导致后续的平台改造移植造成大量的迁移和重构工作,保护了投资(资源投入,包括人力)。
该平台架构可以作为中小企业对微服务平台架构选型的一种参考,当然你可以使用 Kubernetes 替换 Docker Swarm, 毕竟后者成为了小众产品(如果从入手的简洁性,Swarm 依然还是具有吸引力的,几天之类上手),其他子系统的选型也可以作为参考。
关于如何分析基于容器的微服务架构技术选型与设计问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。