微服务架构:基于微服务和Docker容器技术的PaaS云平台架
构设计
微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)
基于微服务架构和Docker容器技术的PaaS云平台建设⽬标是给我们的开发⼈员提供⼀套服务快速开发、部署、运维管理、持续开发持续集成的流程。平台提供基础设施、中间件、数据服务、云服务器等资源,开发⼈员只需要开发业务代码并提交到平台代码库,做⼀些必要的配置,系统会⾃动构建、部署,实现应⽤的敏捷开发、快速迭代。在系统架构上,PaaS云平台主要分为微服务架构、Docker容器技术、DveOps三部分,这篇⽂章重点介绍微服务架构的实施。
实施微服务需要投⼊⼤量的技术⼒量来开发基础设施,这对很多公司来说显然是不现实的,别担⼼,业界已经有⾮常优秀的开源框架供我们参考使⽤。⽬前业界⽐较成熟的微服务框架有Netflix、Spring Cloud和阿⾥的Dubbo等。Spring Cloud是基于Spring Boot的⼀整套实现微服务的框架,它提供了开发微服务所需的组件,跟Spring Boot⼀起使⽤的话开发微服务架构的云服务会变的很⽅便。Spring Cloud包含很多⼦框架,其中Spring Cloud Netflix是其中的⼀套框架,在我们的微服务架构设计中,就使⽤了很多Spring Cloud Netflix框架的组件。Spring Cloud Netflix项⽬的时间还不长,相关的⽂档资料很少,博主当时研究这套框架啃了很多英⽂⽂档,简直痛苦不堪。对于刚开始接触这套框架的同学,要搭建⼀套微服务应⽤架构,可能会不知道如何下⼿,接下来介绍我们的微服务架构搭建过程以及需要那些框架或组件来⽀持微服务架构。
为了直接明了的展⽰微服务架构的组成及原理,博主画了⼀张系统架构图,如下:
从上图可以看出,微服务访问⼤致路径为:外部请求→负载均衡→服务⽹关(GateWay)→微服务→数据服务/消息服务。服务⽹关和微服务都会⽤到服务注册和发现来调⽤依赖的其他服务,各服务集都能通过配置中⼼服务来获得配置信息。
服务⽹关(GateWay)
分布式和微服务的关系⽹关是外界系统(如:客户端浏览器、移动设备等)和企业内部系统之间的⼀道门,所有的客户端请求通过⽹关访问后台服务。为了应对⾼并发访问,服务⽹关以集形式部署,这就意味着需要做负载均衡,我们采⽤了亚马逊EC2作为虚拟云服务器,采⽤ELB(Elastic Load Balancing)做负载均衡。EC2具有⾃动配置容量功能,当⽤户流量达到尖峰,EC2可以⾃动增加更多的容量以维持虚拟主机的性能。ELB弹性负载均衡,在多个实例间⾃动分配应⽤的传⼊流量。为了保证安全性,客户端请求需要使⽤https加密保护,这就需要我们进⾏SSL卸载,使⽤Nginx对加密请求进⾏卸载处理。外部请求经过ELB负载均衡后路由到GateWay集中的某个GateWay服务,由GateWay服务转发到微服务。服务⽹关作为内部系统的边界,它有以下基本能⼒:
1、动态路由:动态的将请求路由到所需要的后端服务集。虽然内部是复杂的分布式微服务⽹状结构,但是外部系统从⽹关看就像是⼀个整体服务,⽹关屏蔽了后端服务的复杂性。
2、限流和容错:为每种类型的请求分配容量,当请求数量超过阀值时抛掉外部请求,限制流量,保护
后台服务不被⼤流量冲垮;党内部服务出现故障时直接在边界创建⼀些响应,集中做容错处理,⽽不是将请求转发到内部集,保证⽤户良好的体验。
3、⾝份认证和安全性控制:对每个外部请求进⾏⽤户认证,拒绝没有通过认证的请求,还能通过访问模式分析,实现反爬⾍功能。
4、监控:⽹关可以收集有意义的数据和统计,为后台服务优化提供数据⽀持。
5、访问⽇志:⽹关可以收集访问⽇志信息,⽐如访问的是哪个服务?处理过程(出现什么异常)和结果?花费多少时间?通过分析⽇志内容,对后台系统做进⼀步优化。
我们采⽤Spring Cloud Netflix框架的开源组件Zuul来实现⽹关服务。Zuul使⽤⼀系列不同类型的过滤器(Filter),通过重写过滤器,使我们能够灵活的实现⽹关(GateWay)的各种功能。
服务注册与发现
由于微服务架构是由⼀系列职责单⼀的细粒度服务构成的⽹状结构,服务之间通过轻量机制进⾏通信,这就引⼊了服务注册与发现的问题,服务的提供⽅要注册报告服务地址,服务调⽤放要能发现⽬标服务。我们的微服务架构中使⽤了Eureka组件来实现服务的注册与发现。所有的微服务(通过配置Eureka服务信息)到Eureka服务器中进⾏注册,并定时发送⼼跳进⾏健康检查,Eureka默认配置是30
秒发送⼀次⼼跳,表明服务仍然处于存活状态,发送⼼跳的时间间隔可以通过Eureka的配置参数⾃⾏配置,Eureka服务器在接收到服务实例的最后⼀次⼼跳后,需要等待90秒(默认配置90秒,可以通过配置参数进⾏修改)后,才认定服务已经死亡(即连续3次没有接收到⼼跳),在Eureka ⾃我保护模式关闭的情况下会清除该服务的注册信息。所谓的⾃我保护模式是指,出现⽹络分区、Eureka在短时间内丢失过多的服务时,会进⼊⾃我保护模式,即⼀个服务长时间没有发送⼼跳,Eureka也不会将其删除。⾃我保护模式默认为开启,可以通过配置参数将其设置为关闭状态。
Eureka服务以集的⽅式部署(在博主的另⼀篇⽂章中详细介绍了Eureka集的部署⽅式),集内的所有Eureka节点会定时⾃动同步微服务的注册信息,这样就能保证所有的Eureka服务注册信息保持⼀致。那么在Eureka集⾥,Eureka节点是如何发现其他节点的呢?我们通过DNS服务器来建⽴所有Eureka节点的关联,在部署Eureka集之外还需要搭建DNS服务器。
当⽹关服务转发外部请求或者是后台微服务之间相互调⽤时,会去Eureka服务器上查⽬标服务的注册信息,发现⽬标服务并进⾏调⽤,这样就形成了服务注册与发现的整个流程。Eureka的配置参数数量很多,多达上百个,博主会在另外的⽂章⾥详细说明。
微服务部署
微服务是⼀系列职责单⼀、细粒度的服务,是将我们的业务进⾏拆分为独⽴的服务单元,伸缩性好,
耦合度低,不同的微服务可以⽤不同的语⾔开发,每⼀个服务处理的单⼀的业务。微服务可以划分为前端服务(也叫边缘服务)和后端服务(也叫中间服务),前端服务是对后端服务做必要的聚合和剪裁后暴露给外部不同的设备(PC、Phone等),所有的服务启动时都会到Eureka服务器进⾏注册,服务之间会有错综复杂的依赖关系。当⽹关服务转发外部请求调⽤前端服务时,通过查询服务注册表就可以发现⽬标服务进⾏调⽤,前端服务调⽤后端服务时也是同样的道理,⼀次请求可能涉及到多个服务之间的相互调⽤。由于每个微服务都是以集的形式部署,服务之间相互调⽤的时候需要做负载均衡,因此每个服务中都有⼀个LB组件⽤来实现负载均衡。
微服务以镜像的形式,运⾏在Docker容器中。Docker容器技术让我们的服务部署变得简单、⾼效。传统的部署⽅式,需要在每台服务器上安装运⾏环境,如果我们的服务器数量庞⼤,在每台服务器上安装运⾏环境将是⼀项⽆⽐繁重的⼯作,⼀旦运⾏环境发⽣改变,就不得不重新安装,这简直是灾难性的。⽽使⽤Docker容器技术,我们只需要将所需的基础镜像(jdk等)和微服务⽣成⼀个新的镜像,将这个最终的镜像部署在Docker容器中运⾏,这种⽅式简单、⾼效,能够快速部署服务。每个Docker容器中可以运⾏多个微服务,Docker容器以集的⽅式部署,使⽤Docker Swarm对这些容器进⾏管理。我们创建⼀个镜像仓库⽤来存放所有的基础镜像以及⽣成的最终交付镜像,在镜像仓库中对所有镜像进⾏管理。
服务容错
微服务之间存在错综复杂的依赖关系,⼀次请求可能会依赖多个后端服务,在实际⽣产中这些服务可能会产⽣故障或者延迟,在⼀个⾼流量的系统中,⼀旦某个服务产⽣延迟,可能会在短时间内耗尽系统资源,将整个系统拖垮,因此⼀个服务如果不能对其故障进⾏隔离和容错,这本⾝就是灾难性的。我们的微服务架构中使⽤了Hystrix组件来进⾏容错处理。Hystrix是Netflix的⼀款开源组件,它通过熔断模式、隔离模式、回退(fallback)和限流等机制对服务进⾏弹性容错保护,保证系统的稳定性。
1、熔断模式:熔断模式原理类似于电路熔断器,当电路发⽣短路时,熔断器熔断,保护电路避免遭受灾难性损失。当服务异常或者⼤量延时,满⾜熔断条件时服务调⽤⽅会主动启动熔断,执⾏fallback逻辑直接返回,不会继续调⽤服务进⼀步拖垮系统。熔断器默认配置服务调⽤错误率阀值为50%,超过阀值将⾃动启动熔断模式。服务隔离⼀段时间以后,熔断器会进⼊半熔断状态,即允许少量请求进⾏尝试,如果仍然调⽤失败,则回到熔断状态,如果调⽤成功,则关闭熔断模式。
2、隔离模式:Hystrix默认采⽤线程隔离,不同的服务使⽤不同的线程池,彼此之间不受影响,当⼀个服务出现故障耗尽它的线程池资源,其他的服务正常运⾏不受影响,达到隔离的效果。例如我们通过andThreadPoolKey配置某个服务使⽤命名为TestThreadPool的线程池,实现与其他命名的线程池隔离。
3、回退(fallback):fallback机制其实是⼀种服务故障时的容错⽅式,原理类似Java中的异常处理。
只需要继承HystixCommand并重写getFallBack()⽅法,在此⽅法中编写处理逻辑,⽐如可以直接抛异常(快速失败),可以返回空值或缺省值,也可以返回备份数据等。当服务调⽤出现异常时,会转向执⾏getFallBack()。有以下⼏种情况会触发fallback:
1)程序抛出⾮HystrixBadRequestExcepption异常,当抛出HystrixBadRequestExcepption异常时,调⽤程序可以捕获异常,没有触发fallback,当抛出其他异常时,会触发fallback;
2)程序运⾏超时;
3)熔断启动;
4)线程池已满。
4、限流:限流是指对服务的并发访问量进⾏限制,设置单位时间内的并发数,超出限制的请求拒绝并fallback,防⽌后台服务被冲垮。
Hystix使⽤命令模式HystrixCommand包装依赖调⽤逻辑,这样相关的调⽤就⾃动处于Hystrix的弹性容错保护之下。调⽤程序需要继承HystrixCommand并将调⽤逻辑写在run()中,使⽤execute()(同步阻塞)或queue()(异步⾮阻塞)来触发执⾏run()。
动态配置中⼼
微服务有很多依赖配置,某些配置参数在服务运⾏期间可能还要动态修改,⽐如:根据访问流量动态调整熔断阀值。传统的实现信息配置的⽅法,⽐如放在xml、yml等配置⽂件中,和应⽤⼀起打包,每次修改都要重新提交代码、打包构建、⽣成新的镜像、重新启动服务,效率太低,这样显然是不合理的,因此我们需要搭建⼀个动态配置中⼼服务⽀持微服务动态配置。我们使⽤Spring Cloud的configserver服务帮我们实现动态配置中⼼的搭建。我们开发的微服务代码都存放在git服务器私有仓库⾥⾯,所有需要动态配置的配置⽂件存放在git服务器下的configserver(配置中⼼,也是⼀个微服务)服务中,部署到Docker容器中的微服务从git服务器动态读取配置⽂件的信息。当本地git仓库修改代码后push到git服务器仓库,git服务端hooks(post-receive,在服务端完成代码更新后会⾃动调⽤)⾃动检测是否有配置⽂件更新,如果有,git服务端通过消息队列给配置中⼼(configserver,⼀个部署在容器中的微服务)发消息,通知配置中⼼刷新对应的配置⽂件。这样微服务就能获取到最新的配置⽂件信息,实现动态配置。
以上这些框架或组件是⽀撑实施微服务架构的核⼼,在实际⽣产中,我们还会⽤到很多其他的组件,⽐如⽇志服务组件、消息服务组件等等,根据业务需要⾃⾏选择使⽤。在我们的微服务架构实施案例中,参考使⽤了很多Spring Cloud Netflix框架的开源组件,主要包括
Zuul(服务⽹关)、Eureka(服务注册与发现)、Hystrix(服务容错)、Ribbon(客户端负载均衡)等。这些优秀的开源组件,为我们实施微服务架构提供了捷径。
【对⽐分析】分布式-微服务-集的区别
1.分布式
将⼀个⼤的系统划分为多个业务模块,业务模块分别部署到不同的机器上,各个业务模块之间通过接⼝进⾏数据交互。区别分布式的⽅式是根据不同机器不同业务。
上⾯:service A、B、C、D 分别是业务组件,通过API Geteway进⾏业务访问。
注:分布式需要做好事务管理。
分布式事务可参考:
2.集模式
集模式是不同服务器部署同⼀套服务对外访问,实现服务的负载均衡。区别集的⽅式是根据部署多台服务器业务是否相同。
注:集模式需要做好session共享,确保在不同服务器切换的过程中不会因为没有获取到session⽽中⽌退出服务。
⼀般配置Nginx*的负载容器实现:静态资源缓存、Session共享可以附带实现,Nginx⽀持5000个并发量。
3.分布式是否属于微服务?
答案是肯定的。的意思也就是将模块拆分成⼀个独⽴的服务单元通过接⼝来实现数据的交互。
4.微服务架构
微服务的设计是为了不因为某个模块的升级和BUG影响现有的系统业务。微服务与分布式的细微差别是,微服务的应⽤不⼀定是分散在多个服务器上,他也可以是同⼀个服务器。
分布式和微服的很相似,只是部署的⽅式不⼀样⽽已。
以上篇幅主要介绍了微服务架构的基本原理,其中有些⽐较细节的东西,⽐如Eureka的各项参数配置说明、动态配置中⼼搭建过程等,博主会在其他的⽂章中做出详细的说明,供⼤家参考。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论