一、微服务
背景-从单体到微服务,架构的演变
太长不看版:互联网的快速发展;敏捷开发 精益方法的深入人心(scrum 用户故事地图 黄金圈法则 披萨饼原则); 容器技术的成熟。
详细版:影响企业“持续快速地响应市场需求的变化”的因素很多,但从企业应用系统架构的角度来讲,就需要一个能够面对变化的,甚至是主动拥抱变化的架构。
那么单体应用架构能不能满足企业应对变化的要求呢?两天到一周的问题修复周期;两周到三周,甚至一两个月的需求变更周期;一个月到两个月的版本发布计划……也许在某些需求比较稳定,市场变化不明显的领域,这样的频率是可以接受的。但是在“你死我活”,竞争激烈的领域,如果只具备这样的响应力则注定是要被动挨打的。
是什么样的原因导致单体应用“快”不起来?所有代码都放在一起,大量紧耦合的代码导致应用模块间的界限日益模糊,改一处而动全身,有时程序员甚至无从下手,拖慢了修复问题和修改变更的速度;当频繁变更时,就需要做大量的回归测试,如果当测试过程中发现问题还要重新修改,延长了测试时间;所有功能都被打进一个发布包中,往往需要彼此等待大部分或所有模块开发,测试完成才能进行统一部署,拖长了发布时间……单体应用就像代步用的马车,你可以增加马匹的数量来增强马车的运输能力,却永远受限于马的速度。这时我们需要一种可以真正提高速度的工具——一辆真正的汽车:微服务。
这两年业界最流行的技术架构话题已经从前后端分离,变成了分布式、微服务、DDD了。微服务架构适合所有的公司吗,业务场景演变到了什么地步才需要考虑上微服务呢?毕竟选择技术架构之前应该考虑业务是否与之匹配,否则分布式、微服务这类繁重的架构设计对一些公司来说就变成了屠龙之技,反而成为一线开发团队的负担。
架构就像一个杂货铺,微服务也只是工具箱,不能有了锤子满世界找钉子,有可能人家只是一颗螺丝钉在等待改锥。言归正传,微服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API。这些服务围绕业务能力来构建,并通过完全自动化部署机制来独立部署。
什么是微服务?
太长不看版:
就是用户太多了 把大服务拆成小服务 来互相协调 最终形成1个能hold住比较多的请求的 1个架构。
详细版:
微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
单体应用:ALL IN ONE
微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;
微服务 Microservices 之父,马丁.福勒,对微服务大概的概述如下:
就目前而言,对于微服务业界并没有一个统一的、标准的定义(While there is no precise definition of this architectural style ) 。
但通常在其而言,微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。
服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API ) 。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。
另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务。可以使用不同的语言来编写服务,也可以使用不同的数据存储。
根据马丁.福勒的描述,我总结了以下几点:
①小服务
小服务,没有特定的标准或者规范,但他在总体规范上一定是小的。
②进程独立
每一组服务都是独立运行的,可能我这个服务运行在 Tomcat 容器,而另一个服务运行在 Jetty 上。可以通过进程方式,不断的横向扩展整个服务。
③通信
过去的协议都是很重的,就像 ESB,就像 SOAP,轻通信,这意味着相比过去更智能更轻量的服务相互调用,就所谓 smart endpoints and dumb pipes。
这些 Endpoint 都是解耦的,完成一个业务通信调用串起这些 Micro Service 就像是 Linux 系统中通过管道串起一系列命令业务。
过去的业务,我们通常会考虑各种各样的依赖关系,考虑系统耦合带来的问题。微服务,可以让开发者更专注于业务的逻辑开发。
④部署
不止业务要独立,部署也要独立。不过这也意味着,传统的开发流程会出现一定程度的改变,开发的适合也要有一定的运维职责。
⑤管理
传统的企业级 SOA 服务往往很大,不易于管理,耦合性高,团队开发成本比较大。
微服务,可以让团队各思其政的选择技术实现,不同的 Service 可以根据各自的需要选择不同的技术栈来实现其业务逻辑。
总结:
它将应用程序构建为以业务领域为模型的小型自治服务集合。通俗地说,你必须看到蜜蜂如何通过对齐六角形蜡细胞来构建它们的蜂窝状物。他们最初从使用各种材料的小部分开始,并继续从中构建一个大型蜂箱。这些细胞形成图案,产生坚固的结构,将蜂窝的特定部分固定在一起。这里,每个细胞独立于另一个细胞,但它也与其他细胞相关。这意味着对一个细胞的损害不会损害其他细胞,因此,蜜蜂可以在不影响完整蜂箱的情况下重建这些细胞。
微服务的利与弊
为什么用微服务呢?因为好玩?不是的。下面是我从网络上找到说的比较全的优点:
优点是每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求。
开发简单、开发效率提高,一个服务可能就是专一的只干一件事。
微服务能够被小团队单独开发,这个小团队是 2 到 5 人的开发人员组成。
微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。
微服务能使用不同的语言开发。
易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如 Jenkins,Hudson,bamboo。
微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。微服务允许你利用融合最新技术。
微服务只是业务逻辑的代码,不会和 HTML,CSS 或其他界面组件混合。
每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一数据库。
总的来说,微服务的优势,就是在于,面对大的系统,可以有效的减少复杂程度,使服务架构的逻辑更清晰明了。
但是这样也会带来很多问题,就譬如分布式环境下的数据一致性,测试的复杂性,运维的复杂性。
工作中微服务的问题
去年开始,我们启动了一个新项目,基于这个机会,我决定使用相对的微服务架构来实践新的产品(没有历史包袱的感觉真好)。但是,微服务架构在某些方面会确实增大我们的开发成本和运维成本:
错误排除 由于我们有很多的服务,一次请求可能经过多个逻辑服务器,错误散落在不同的服务中,为我们的错误排查带来了困难。
日志分析 服务越多,对于日志的排查就越困难,最好能把服务的日志集中收集并分析。
基础设施 每个服务有互相独立的MySQL、Redis,公共服务方面需要高可用的服务发现,监控报警系统,调用链路分析,日志收集储存设施等。
我们在业务上拆分不同的服务后,接下去要做的所有事情几乎都是在解决上面的问题(也就是所谓的服务治理问题)。
二、spring-cloud各组件
1.EureKa
网上对eureka介绍的文章有很多,这里我就不详细介绍了,主要围绕这几点来简单总结一下:
eureka能做什么?
其实 eureka最主要的功能就两大点 服务注册 、服务发现,
eureka服务注册
会将所有eureka的client端进行统一注册到eureka服务端,然后对所有注册了的客户端进行心跳检查并标记或者排除掉不可用的客户端。
eureka服务发现
eureka客户端会获取所有服务端已注册的服务信息,服务信息包括注册时候的服务名、实际ip地址,而且eureka客户端结合Ribbon、或者Feign可直接使用服务名来对该服务进行请求调用。
为什么需要eureka?
至于为什么需要eureka呢,其实这个问题很简单,比方说我们这个模拟业务里面的商品服务,在实际的场景中我们可能会部署多个商品服务的实例,那么如果我们不采用注册中心的话,所有依赖商品服务的其他服务就必须在各自的配置里面配置商品服务的地址,然后再采用一些负载均衡的算法来对商品服务进行请求,并且也无法检测各个实例的存活情况,当然你也可以自己实现一套心跳机制… 好了 不说了 相信各位小伙伴应该已经能想到用eureka有多方便了,其实不止eureka可以做服务注册与发现 还有consul、zookeeper等,后续也会有专门的文章对其进行讲解。
eureka和其他同类产品优势是什么?
这个疑问我相信也是大家比较想知道的,至于为什么服务注册与发现首选Eureka,而不用consul、zookeeper呢?
在分布式系统领域我们始终摆脱不了CAP理论(C:一致性,A:服务可用性,P分区容错性),其中P是必须成立的,如果大家不清楚CAP理论的话,请自行google一下吧,这里就不再对其进行介绍了;eureka保证了AP,consul和zookeeper保证了CP。
采用eureka作为服务中心,我们可以保证服务可用性,通俗点来讲就是如果往eureka服务集群的某个eureka服务节点进行注册的话,eureka不会强制将其全部都复制到集群中的其他节点上去,也不保证注册信息有没有复制成功,虽然说可能会出现各个eureka服务节点的数据不一致性问题,但这并不影响其正常使用,我们的业务服务可以对所有eureka服务节点都进行注册当有其他业务服务注册上来、或者业务服务注册信息有变化了,请求中一个eureka服务节点可能会查看不到最新的注册数据,但请求另一个eureka服务节点就能查看到最新的注册数据,也就是说eureka舍弃了 强一致性 来保证了整体eureka服务的 高可用性。
而且eureka还有一个特点,就是当出现一些网络问题导致eureka心跳机制响应的缓慢或者丢失心跳,eureka并不会马上吧这些暂时不可用的服务移除掉,而是会对暂时不可用的服务开启保护模式,但是如果持续多少秒后(默认90秒)还没有接收到该某些服务的心跳的话,则会吧对应服务移除掉。
对比于consul、zookeeper来说,这两者更偏向于保证 数据的一致性 ,从而降低了 可用性;consul的服务注册相比 Eureka 会稍慢一些。因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功,而且当consul集群的Leader 挂掉时,重新选举期间整个 Consul集群是不可用的,所以其保证了强一致性但牺牲了可用性。zookeeper也是保证了CP,也就是说随便访问zookeeper集群的几个节点都能一致的数据,但是zookeeper并不能保证请求的 可用性 ,因为在一些特殊的极端场景,zookeeper会舍弃掉一部分请求,客户端需要重新请求才可能能获取到数据,而且zookeeper的master挂掉也需要重新选取新的master,并且这期间zookeeper集群是处于不可用状态的,而且最致命的就是,zookeeper的选举耗时会比较长,如果一单遇到网络波动,都会导致进行master的选举,从而增加zookeeper的不可用时间。
总的来说Eureka更加符合服务注册、发现的场景,虽然说现在Eureka2.x闭源了,但是Eureka1.x目前还是有很多大公司在商用了,而且最主要的服务注册与发现功能也得到了很多用户的证实,所以对于后续只是单纯的做服务注册与发现的话 Eureka至少还是个不二的选择,当然为了更长远的考虑,或者不只是单纯的想要服务注册于发现功能的话,也可以使用consul来搭建服务注册中心,并且consul还支持K-V键值对存储以及其他扩展功能;但是zookeeper的话,因为其中一些特性个人觉得还是不太适合做服务注册中心。
(待续)