十几年前就有一些公司开始践行服务拆分以及SOA,六年前有了微服务的概念,因而你们开始思考SOA和微服务的关系和区别。最近三年Spring Cloud的大火把微服务的实践推到了高潮,而近两年K8S在容器编排的地位肯定以后你们又开始实践起以K8S为核心的云原生思想和微服务的结合如何去落地,2018年又多出一个ServiceMesh服务网格的概念,你们又在思考如何引入落地ServiceMesh,ServiceMesh和K8S以及Spring Cloud的关系如何等等。程序员
确实有点乱了,这一波又一波的热潮,几乎每两年都会来一波有关微服务架构理念和平台,许多公司还没完成微服务的改造就又提出了服务+容器道路,又有一些公司打算从微服务直接升级成ServiceMesh。本文尝试总结一下我见过的或实践过的一些微服务落地方式,而且提出一些本身的观点,但愿抛砖引玉,你们能够畅谈一下本身公司的微服务落地方式。spring
(图中灰色部分表明元数据存储区域,也就是Service和Endpoint关系所保存的地方,以后全部的图都是这样)数据库
其实在2006年在使用.NET Remoting作服务拆分的时候(其实当时咱们没有意识到这叫服务拆分,这是打算把一些逻辑使用独立的进程来承载,以Windows服务形式安装在不一样服务器上分散压力),咱们使用了F5来作服务的负载均衡。没有所谓的服务发现,针对每个服务,咱们直接在程序配置文件中写死F5的IP地址和端口,使用Excel来记录全部服务在F5的端口地址以及服务实际部署的IP:端口,而后在F5进行配置。F5在这里作了负载均衡、简单的路由策略(相同的客户端老是优先路由到相同的后端)以及简单的白名单策略等等。后端
以后尝试过这种改进版的古典玩法。相比v0.1的区别是,再也不使用硬件F5了,而是使用几组软件反向代理服务器,好比Nginx来作服务负载均衡(若是是TCP的负载均衡的话能够选择HaProxy),Nginx的配置会比F5更方便并且还不花钱。因为生产环境Nginx多是多组,客户端不在配置文件中写死Nginx地址而是把地址放到了配置中心去,而Nginx的配置由源码仓库统一管理,运维经过文件同步方式或其它方式从源码仓库拉取配置文件下发到不一样的Nginx集群作后端服务的配置(Nginx的配置也不必定须要是一个大文件放全部的配置,能够每一组服务作一个配置文件更清晰)。缓存
虽然个人标题说这是古典玩法,可是能够说不少公司若是没有上RPC,没有上Spring Cloud,也没有上K8S的话极可能就是这样的玩法。不管是v0.2仍是v0.1,本质上服务是固定在虚拟机或实体机部署的,若是须要扩容,须要迁移,那么确定须要修改反向代理或负载均衡器的配置。少数状况下,若是调整了反向代理或负载均衡器的IP地址,那么还可能会须要修改客户端的配置。安全
SOA的一个特色是使用了服务总线,服务总线承担了服务的发现、路由、协议转换、安全控制、限流等等。2012年我参与了一个大型MMO游戏《激战2》项目的技术整合工做,这个游戏整个服务端就是这种架构。它有一个叫作Portal的服务总线,全部游戏的十几个子服务都会把本身注册到服务总线,无论是什么服务须要调用什么接口,都是在调用服务总线,由服务总线来进行服务的寻址路由和协议转换,服务总线也会作服务的精细化限流,每个用户都有本身的服务请求队列。这种架构的好处是简单,服务总线承担了全部工做,可是服务总线的压力很大,承担了全部的服务转发工做。同时须要考虑服务总线自己如何进行扩容,若是服务总线是有状态的,显然要进行扩容不是这么简单。对于游戏服务器来讲,扩容可能不是一个强需求,由于游戏服务自然会按照大区进行分流,一个大区的最大人数上限是固定的。服务器
貌似互联网公司这样玩的很少,传统企业或是游戏服务端是比较适合服务总线这种架构的,若是服务和服务之间的协议不统一的话,要在客户端作协议转换的工做比较痛苦,若是能够由统一的中间层接入全部协议统一进行转换的话,客户端会比较轻量,可是这种架构的很大问题在于服务总线的扩容和可靠性。架构
上图是大多数RPC框架的架构图。大多数早期的微服务实践都是RPC的方式,最近几年Spring Cloud盛行后其实Spring Cloud的玩法也差很少,只是Spring Cloud推崇的是JSON over HTTP的RESTful接口,而大多数RPC框架是二进制序列化over TCP的玩法(也有JSON over HTTP的RPC)。并发
其实RPC框架我我的喜欢JSON over HTTP,虽然咱们知道HTTP和JSON序列化性能确定不如一些精简的二进制序列化+TCP,可是优势是良好的可读性、测试方便、客户端开发方便,并且我不认为15000的QPS和20000的QPS对于通常应用有什么区别。负载均衡
总的来讲,咱们会有一个集群化的分布式配置中心来充当服务注册的存储,好比ZK、Consul、Eureka或etcd。咱们的服务框架会有客户端和服务端部分,客户端部分会提供服务的发现、软负载、路由、安全、策略控制等功能(可能也会经过插件形式包含Metrics、Logging、Tracing、Resilience等功能),服务端部分对于RPC框架会作服务的调用也会辅助作一些安全、策略控制,对于RESTful的话就服务端通常除了监控没有额外的功能。
好比使用Spring Cloud来玩,那么:
在以前《朱晔和你聊Spring系列S1E8:凑活着用的Spring Cloud(含一个实际业务贯穿全部组件的完整例子)》一文中,我有一个完整的例子介绍过Spring Cloud的这套玩法,能够说的确Spring Cloud给了咱们构建一套微服务体系最基本的东西,咱们只须要进行一些简单的扩展和补充,好比灰度功能,好比更好的配置服务,就彻底能够用于生产。
这种模式和以前0.x的很大区别是,服务的注册有一个独立的组件,注册中心完成,经过配合客户端类库的服务发现,至少服务的扩容很轻松,扩容后也不须要手动维护负载均衡器的配置,至关于服务端从死到活的一个重大转变。并且在1.0的时代,咱们更多看到了服务治理的部分,开始意识到成百上千的服务,若是没有Metrics、Logging、Tracing、Resilience等功能来辅助的话,微服务就是一个灾难。
Spring Cloud已经出了G版了,表示Netflix那套已经进入了维护模式,许多程序员表示表示扶我起来还能学。我认为Spring Cloud这个方向实际上是挺对的,先有开源的东西来填补空白,慢慢再用本身的东西来替换,可是开发比较苦,特别是一些公司基于Spring Cloud辛苦二次开发的框架围绕了Netflix那套东西来作的会比较痛苦。总的来讲,虽然Spring Cloud给人的感受很乱,变化很大,大到E到G版的升级不亚于在换框架,并且组件质量层次不齐,可是它确实是一无全部的创业公司可以起步微服务的很少的选择之一。若是没有现成的框架(不是说RPC框架,RPC框架虽是微服务功能的80%重点,但倒是代码量20%的部分,工做量最大的是治理和整合那套),基于Spring Cloud起步微服务,至少你能够当天起步,1个月完成适合本身公司的二次开发改造。
K8S或者说容器调度平台的引入是比较革命性的,容器使得咱们的微服务对环境的依赖能够打包整合进行随意分发,这是微服务节点能够任意调度的基础,调度平台经过服务的分类和抽象,使得微服务自己的部署和维护实现自动化,以及实现更上一层楼的自动伸缩。在1.x时代,服务能够进行扩缩容,可是一切都须要人工介入,在2.x时代,服务自己在哪里存在甚至有多少实例存在并不重要,重要的只是咱们有多少资源,但愿服务的SLA是怎么样的,其他留给调度平台来调度。
若是说1.0时代你们纠结过Dubbo仍是Spring Cloud,2.0时代我相信也有一些公司上过Mesos的“贼船”,咱们不是先知很难预测什么框架什么技术会在最后存活下来,可是这倒是也给技术带来了很多痛苦,相信仍是有很多公司在干Mesos转K8S的事情。
若是引入了K8S,那么服务发现能够由K8S来作,不必定须要Eureka。咱们能够为Pod建立Service,经过Cluster虚拟IP的方式(如上图所示,经过IP tables)路由到Pod IP来作服务的路由(除了Cluster IP方式也有的人对于内部链接会采用Ingress方式去作,路由方面会更强大,不过这是否是又相似v0.2了呢?)。固然,咱们还能够更进一步引入内部DNS,使用内部域名解析成Cluster IP,客户端在调用服务的时候直接使用域名(域名能够经过配置服务来配置,也能够直接读取环境变量)便可。若是这么干的话其实就没有Eureka啥事了,有的公司没有选择这种纯K8S服务路由的方式仍是使用了注册中心,若是这样的话其实服务注册到注册中心的就是Pod IP,仍是由微服务客户端作服务发现的工做。我更喜欢这种方式,我以为K8S的服务发现仍是弱了一点,并且IP tables的方式让人没有安全感(IPVS应该是更好的选择),与其说是服务发现,我更愿意让K8S只作容器调度的工做以及Pod发现的工做。
虽然K8S能够作一部分服务发现的工做,咱们仍是须要在客户端中去实现更多的一些弹力方面的功能,所以我认为2.0时代只是说是微服务框架结合容器、容器调度,而不能是脱离微服务框架自己彻底依靠K8S实现微服务。2.0和1.0的本质区别或者说加强仍是很明显,那就是咱们能够全局来统筹解决咱们的微服务部署和可靠性问题,在没有容器和容器调度这层抽象以前,有的公司经过实现自动化虚拟机分配拉起,加上自动化初始脚原本实现自动的微服务调度扩容,有相似的意思,可是很是花时间并且速度慢。K8S真正让OPS成为了DEV而不是执行者,让OPS站在整体架构的层面经过DEV(咱不能说开发DSL文件不算开发吧)资源和资源之间的关系来统筹整个集群。在只有十几个微服务若干台服务器的小公司可能没法发挥2.0容器云的威力,可是服务器和服务一多,纯手工的命令式配置容易出错且难以管理,K8S真的释放了几十个运维人力。
在以前提到过几个问题:
因而ServiceMesh服务网格的概念腾空而出,巧妙解决了这几个问题:
说了这么多ServiceMesh的优点,咱们来看一下这种模式的性能问题。想一下各类模式下客户端要请求服务端整个HTTP请求(跳)次数:
总的来讲,3跳并非ServiceMesh的瓶颈所在,而更多的可能性是Istio的倔强的架构理念。Istio认为策略和遥测不该该耦合在Sidecar Proxy应该放到Mixer,那么至关于在调用服务的时候还须要额外增长Mixer的同步请求(来得到策略方面的放行)。Istio也在一直优化这方面,好比为Mixer的策略在Proxy作本地缓存,为遥测数据作批量上报等等。虽然通过层层优化,可是Istio目前的TPS不足2000,仍是和通常的RPC能达到的20000+有着十倍的差距,说不定未来Istio会有架构上的妥协,把Mixer变为非直接依赖,策略方面仍是采用相似Pilot统一管理配置下发的方式,遥测方面仍是由Sidecar直接上报数据到Mixer。
我我的认为,ServiceMesh是一个很是正确的道路,并且ServiceMesh和K8S结合会更好,理由在于:
可是,能够看到目前ServiceMesh还不算很是成熟,Istio在不断优化中,Linkerd 2.x也想再和Istio拼一下,到底谁会胜出还难以知晓,通过以前Dubbo vs Spring Cloud的折腾,Mesos vs K8S的折腾,VM vs Docker的折腾,是否还能经得起折腾Istio vs Linkerd 2呢?我建议仍是再看一看,再等一等。
以前看到过ShardingSphere受到ServiceMesh的理念影响提出了DB Mesh的架构。其实DB Proxy的中间件已经存在不少年了(集中化的Proxy相似服务总线的方式),DB Mesh把Proxy也变为轻量的Sidecar方式,DB的访问也都走本地代理。那么这里我也在想,是否是有可能全部东西都有本地的代理呢?
做为应用服务自己而言,只须要和本地代理作通信调用外部服务、缓存、数据库、消息队列,不须要关心服务和资源所在何地,以及背后的实际服务的组件形态。固然,这只是一个畅想了,对于有状态的资源,Mesh的难度很大,对于相似DB这样的资源由于调用层次并不复杂,也不太会存在异构场景,Mesh的意义不大,综合起来看Everything Mesh的投入产出比相比Service Mesh仍是小不少。
若是搞Java微服务的话,Spring Boot是离不开的,可是是否要用Spring Cloud呢?个人观点是,在目前阶段若是没有什么更好的选择,仍是应该先用。Spring Cloud和K8S首先并非矛盾的东西,K8S是偏运维的,主要作资源整合和管理,若是完全没有服务治理框架纯靠K8S的话会很累,并且功能不完整。开发和架构能够在Spring Cloud方面深耕,运维能够在容器和K8S方面发力,两套体系能够协做造成目前来讲比较好的微服务基石。至于K8S的推行,这必定是一个正确的方向,并且和软件架构方面的改进工做一点不矛盾,毕竟K8S是脱离于具体语言和平台的。
至于Service Mesh,它作的事情和Spring Cloud是有不少重复的,在未来Istio若是发展的更好的状况下,应该能够替代Spring Cloud,开发人员只须要用Spring Boot开发微服务便可,客户端方面也能够很瘦,不须要过多关心服务如何通信和路由,服务的安全、通信、治理、控制都由Service Mesh进行(可是,是否有了Sidecar,客户端真的彻底不须要SDK了呢?我认为可能仍是须要的,对于Tracing,若是没有客户端部分显然是不完整的,虽然Sidecar是localhost可是仍是跨进程了)。
Spring Cloud目前虽然针对K8S和Istio作了一些整合,可是并没看到一套针对ServiceMesh的最佳实践出来,是否未来Spring Cloud会在微服务这方面作退化给ServiceMesh让步还不得而知。总的来讲,长期我看好Spring Boot + K8S + Istio的组合,短时间我认为仍是Spring Boot + K8S + Spring Cloud这么用着。
本文总结了各类微服务落地的形态,因为技术多样,各类理念层出不穷,形成了微服务的落地方式真的很难找到两家相同的公司,本文中咱们介绍了:
固然,可能还会有更多的方式:
也可能不少公司在混用各类方式,具备N套服务注册中心,正在作容器化迁移,想一想就头痛,微服务的理念层出不穷伴随着巨头之间的技术战役,苦的仍是架构和开发,固然,运维可能也苦,2019新年快乐,Enjoy微服务!