专栏名称: 运维帮
互联网技术分享平台,分享的力量。帮主一直坚信技术可以改变世界,从毕业到现在干了15年运维,有许多话要和你说。
目录
相关文章推荐
InfoQ架构头条  ·  代码界的“瘟疫”?卡帕西“Vibe ... ·  2 天前  
运维  ·  资源节省 81%,作业帮 MySQL ... ·  3 天前  
51好读  ›  专栏  ›  运维帮

一个运维老鸟眼中的DevOps和微服务

运维帮  · 公众号  · 运维  · 2017-02-17 18:37

正文

单体应用 VS 微服务


让我们先从运维的真实场景出发,来看一下单体应用存在的问题。这里先分享两个真实的生产案例:

案例一是某核心业务系统,所有的业务逻辑代码都打包在同一个WAR包里部署,运行了将近几百个同构的实例在虚拟机上。某次因为应用包中的一个功能模块出现异常,导致实例挂起,整个应用都不能用了。因为它是一个单体,所以尽管有几百个实例在运行,但是这几百个实例都是异常的。业务系统是经过多年建设起来的,排查起来也很复杂,最终整个业务系统瘫痪了近六个小时才恢复。同时,因为有多个前台系统也调用了这个后台系统,导致所有要调用的前台系统也都全部瘫痪了。设想一下,如果这个场景使用的是微服务架构,每个微服务都是独立部署的,那影响的也只是有异常的微服务和其他相关联的服务,而不会导致整个业务系统都不能使用。


另外的案例是一个客服系统,这个系统有一个特点,早上八点的时候会有大量的客服登录。这个登录点是全天中业务并发量最高的时间点,登录时系统需要读取一些客户信息,加载到内存。后来一到早上客服登录时,系统经常出现内存溢出,进而导致整个客服系统都用不了。当时系统应对这种场景做架构冗余时,并不是根据单独的业务按需进行扩展,而是按照单体应用的长板进行冗余。比如说早上八点并发量最高,单点登陆模块业务需求非常大,为适应这个时间点这个模块的业务压力,系统会由原来的八个实例扩展到十六个实例,这时的扩展是基于整个系统的。但事实上,在其他时间段,这个单点登陆模块基本不使用,且监控的数据显示,主机的资源使用情况基本在40%以下,造成了很大的资源浪费。所以在一个大型的业务系统中,每个服务的并发压力不一样,如果都按压力最大的模块进行整体扩展,就会造成资源的浪费,而在微服务的模式下,每个服务都是按自身压力进行扩展的,就可以有效的提高资源利用率。


从这两个例子中,我们可以看出,单体应用存在如下两个问题:一个是横向扩展时需要整体扩展,资源分配最大化,不能按需扩展和分配资源;另一个是如果单体中有一个业务模块出现问题,就会是全局性灾难,因为所有业务跑在同一个实例中,发生异常时不具备故障隔离性,会影响整个业务系统,整个入口都会存在问题。


因此,我们当时考虑把综合业务拆分,进行更好的资源分配和故障隔离。

图 1


下面我们看一下单体应用和微服务的对比,如图1所示。这里从微服务带来的好处和额外的复杂性来讲。


微服务的好处:


  1. 局部修改,局部更新。当运维对一个单体应用进行修改时,可能要先把整个包给停了,然后再去修改,而微服务只需逐步修改和更新即可;

  2. 故障隔离,非全局。单体应用是跑在一起,所以只要一个模块有问题,其他就都会有问题。而微服务的故障隔离性、业务可持续性都非常高;

  3. 资源利用率高。单体应用的资源利用率低,而使用微服务,可以按需分配资源,资源利用率会非常高。


微服务带来的复杂性:


微服务间较强的依赖关系管理。以前单体应用是跑在一起,无依赖关系管理,如果拆成微服务依赖关系该如何处理,比如说某个微服务更新了会不会对整个系统造成影响。


部署复杂。单体应用是集中式的,就一个单体跑在一起,部署和管理的时候非常简单,而微服务是一个网状分布的,有很多服务需要维护和管理,对它进行部署和维护的时候则比较复杂。


如何更好地利用资源。单体应用在资源分配时是整体分配,扩展时也是整体扩展,数量可控,而在使用微服务的情况下,需要为每一个微服务按需分配资源,那么该为每个微服务分配多少资源,启动多少个实例呢,这也是非常大的问题。


监控管理难。以前我们用Java,就是一个单体应用,监控和管理非常简单,因为它就是一个1,但是使用微服务它就是N个,监控管理变得非常复杂。另外是微服务之间还有一个协作的问题。


基于容器构建微服务架构


使用微服务,第一步是要构建一个一体化的DevOps平台,如图2。如果你不使用DevOps做微服务的话,整个环境会变得非常的乱、非常的糟糕。它会给你的整个开发、测试和运维增加很多成本,所以第一步我们是提高DevOps的能力,能够把它的开发、部署和维护进行很完美的结合,才可以说我们真正能够享受到微服务架构的福利。

图 2


容器的出现给微服务提供了一个完美的环境,因为我们可以:

  1. 基于容器做标准化构建和持续集成、持续交付等。

  2. 基于标准工具对部署在微服务里面的容器做服务发现和管理。

  3. 透过容器的编排工具对容器进行自动化的伸缩管理、自动化的运维管理。


所以说,容器的出现和微服务的发展是非常相关的,它们共同发展,形成了一个非常好的生态圈。下面详细讲下DevOps的各个模块。


持续集成与持续发布


持续集成的关键是完全的自动化,读取源代码、编译、连接、测试,整个创建过程自动完成。我们来看一下如何用Docker、Maven、Jenkins完成持续集成。

图 3


如图3所示。首先是开发人员把程序代码更新后上传到Git,然后其他的事情都将由Jenkins自动完成。那Jenkins这边发生什么了呢?Git在接收到用户更新的代码后,会把消息和任务传递给Jenkins,然后Jenkins会自动构建一个任务,下载Maven相关的软件包。下载完成后,就开始利用Maven Build新的项目包,然后重建Maven容器,构建新的Image并Push到Docker私有库中。然后删除正在运行的Docker容器,再基于新的镜像重新把Docker容器拉起来,自动完成集成测试。整个过程都是自动的,这样就简化了原本复杂的集成工作,一天可以集成一次,甚至是多次。


依赖关系管理


前面讲到,当微服务多的时候,依赖关系管理也会比较复杂,现在比较流行的是基于消费者驱动的契约管理。在开发一个微服务时,并不需要另外一个微服务开发完后再做集成测试,而是使用契约的方式。契约通过提供标准化的输出,说明请求的内容、回复的内容、交换的数据,开发微服务时符合契约里这些条件即可。

图 4


如图4所示,微服务A通过模拟与微服务B的交互,将交互内容保存在契约里,而微服务B开发时需满足这个契约里的条件,这样就不需要A和B完全完成了才能做测试。当很多微服务与微服务B关联时,每个微服务通过契约告诉微服务B请求的内容、正确的响应和请示的数据,然后微服务B通过契约模拟这个测试过程,而其他的微服务则需要满足这个契约。当微服务进行升级时,也是要先满足所有契约,这样微服务间的关系就可以更好的进行管理。


典型的微服务架构


图5是典型的微服务架构模型,采用的是Kubernetes框架。把业务系统拆分成很多的微服务,然后通过服务注册的方式去发现整个生产环境中所有的微服务,通过负载均衡组件进行分发,再用服务调度去进行弹性伸缩,而客户端则只需要通过API网关访问微服务。除此之外,微服务的运维也很重要。开发是实现功能性需求,而在实际的生产环境中,我们更应该关心非功能性的需求。因为即使功能实现了,跑到生产上却不能用,功能开发再完美也没有用。

图 5


服务发现与负载均衡


服务发现与负载均衡使用的是Kubernetes的架构,如图6。每一个微服务都有一个IP和PORT,当调用一个微服务时,只需要知道微服务的IP,而不需要关心容器的IP,也不需要关心pod的IP。虽然每个pod也有IP和PORT,但当一个pod启动时,就会把pod的IP和PORT注册到服务发现模块,再进行负载均衡。所以当多个pod启动时,对于用户来说还是只需要知道service的IP,不需要知道后端启动了多少pod、IP是多少,这就解决了网络的问题。

图 6


日志集中式管理

图 7


以前单体的情况下,单体的数量少,日志数量也相应比较少,而在微服务架构下,因为拆分成了很多微服务,相应的日志会非常多且散,这种情况下需要对日志进行集中的管理。我们可以在每个容器里跑日志监控,把所有日志采集进行集中管理和存储,再通过简易操作的UI界面进行索引和查询。


监控管理

图 8


然后就是监控方面了。微服务的量是非常大的,这个时候如何有效地监控是极其重要的。我们刚开始做监控的时候,有几百个实例对同一个关键字进行监控,出故障后会收到几百条短信,因为每一个实例都会发一条短信。这时候严重的致命性的报警就会看不到,因为手机信息已经爆炸了,所以要对报警进行分级,精确告警,最重要的是尽量让故障在发生之前灭亡。因此,在做监控时要对故障提前进行判断,先自动化处理,再看是否需要人为处理,然后通过人为的干预,有效的把故障在发生之前进行灭亡。







请到「今天看啥」查看全文