分布式服务架构
1.应用特点
- 多环境多系统的交互
多环境,一指的是包括语言环境,一般来说,整个企业级应用有主流开发语言,比如java、C++、.net等,整个企业还会根据不同的情况,往往会有不同的语言开发出来的服务,比如说,在一定需求的情况下,需要用PHP的代码来调用java写的http的接口或者因为安全性的问题java也可以用C++生成的本地方法;二指的是网络等一些硬件环境,企业级应用在和用户打交道的时候,网络环境等一些硬件环境的不同,企业级应用往往要去适应这些差异。举个例子,企业需要考虑到电信运营商的不同,通常会多机房多节点的部署,同时可以防止网线被挖断等一些事故。
多系统,比如说在应用中可能会调用一些外部的环境,一些第三方的接口,怎么针对外部系统的服务做网络优化,安全隔离等很多准备
- 海量数据、高并发【用户访问并发】、高TPS【每秒吞吐能力】
- 安全等级高
包括用户的敏感数据存储,服务器的防火墙以及各层次之间的服务器隔离级别,都有严格的要求,一旦漏洞被利用泄露了用户信息,对企业和用户都会造成巨大影响。
- 自动化集群管理
企业应用从代码,到构建打包,到推送到各个服务器,到启动运行,都应该是自动化进行的,并且有备份可以回滚的
2.架构
2.1原则
2.1.1CAP原则
- C一致性:数据变动要同步
- A高性能,高可用性:随着数据访问量增长,应用始终能够保证高性能的查询和相应的操作,或者任意节点的应用不可用也不会对整个分布式系统提供服务造成影响,采用传统数据库,如果单表数据增长到一定程度,都会有性能下降,所以好的架构设计,需要规避数据库的性能下降
- P分区容错性:系统应该能持续提供服务,即使系统内部有消息丢失。分区容错性有一个前提,就是对分区的管理,比如对数据的分区管理,将一份数据同步成几分数据,那么几分数据都将用于查询,假如在数据同步的时候,有消息丢失,如果有分区容错性,那这次操作仍将成功,不会影响用户。
2.1.2复杂的事情简单化
2.2架构的目标
- 高速缓存
redis、Memcached等技术
- 并行计算
充分利用企业资源来提升最大化的服务
- 负载均衡
均匀的分配任务给每个服务器,使得每个服务器的压力都被匀分
- 数据备份
主备份,线上库到离线库备份
- 异地容灾
备用多个机房存储数据库,来面对网络不稳定的情况
- 业务分离
拆分大应用为多个小应用,以服务化的方式暴露接口,简化应用
2.3架构发展
2.3.1 原始版
原始版只有用户、服务器、数据库这三者之间的关系,对于初学者,和正在开发简单应用的程序员来说,这个模式是最为熟悉的。数据库一般为mysql或者oracle;服务器一般是单台的虚拟机,用户访问量也比较少。只是提供了最简单的功能,而没有对企业架构进行更深层次的挖掘。
特点
- 单节点:几乎只有一台机器
- 几乎无容灾:如果机器挂了只能重启
- 负载能力低:访问量比较少
- 维护简单:只有一台服务器,所以对应用监控比较简单,数据库管理比较简单,企业部署成本比较低
2.3.2 动静分离版
与原始版最大区别,加入Nginx,通过Nginx来访问静态资源,同时用户在访问web应用时都以REST形式的API来访问,通过ajax请求来获取数据,提交数据,极大减少了和用户交互的流量,html、js、css大资源通过Nginx传送给用户,降低交互流量,从而使得服务器能够负载更多的用户,而且Nginx还有负载均衡的功能,可以增加服务器部署,通过Nginx的负载均衡,均匀的分配到各个机器上。使用了框架spring,Struts,mybatis等,通过这些框架,来更高效的访问数据库,或者建立视图层,节省开发时间。总的来说,动静分离版就是加入了Nginx,使用Nginx来访问静态资源,同时增加了服务器的部署,再使用Nginx来做负载均衡,web应用使用json和用户交互,减少了交互之间的流量,提升了服务器性能,同时对开发来说,大量使用第三方框架,通过依赖框架来节省开发的时间,如果使用Nginx来代理,同时使用REST API相当于把接口暴露给用户,一旦接口有任何安全性问题,就会造成严重的后果,由于部署了多台应用,在某台机器上的应用无法访问到另一台机器上的session,所以session持久化是一个问题,无法通过session来获取用户访问的一些数据,只有将简单的数据写到Cookie里,服务器从对应的Cookie中读取到对应的值,而Cookie一旦被修改,也一样会造成一些问题。大多数小型企业都是采用动静分离版这种结构
特点
- Nginx访问静态资源
- Nginx负载均衡
- 应用分离
- 依赖框架
- 安全性低【暴露REST API】
- Session 持久化问题【部署了多台服务器,Session持久化成为问题】。
2.3.3 缓存版
加入高速缓存(Redis、Memcached),支持key-value形式的查询,相对于传统数据库来说,性能非常好,可以达到6w/s查询量。引用高速缓存来提升服务的性能。
高速缓存有两种情况:
- 基于请求的缓存,当http请求发起,先去查询高速是否有结果,没有的话,查询数据库,写入高速缓存,返回给用户;
- 基于查询结构缓存,查询数据库前,先根据相应条件查询高速缓存,如果查询到结果,再封装返回给用户。没有的话则查询数据库,写入缓存再返回给用户;
利用高速缓存来做Session会话持久,在动静分离版中,由于部署了多台机器,由于一台机器不能访问另外一台机器的Session,所以讲Session公共存储于高速缓存之中,当Http请求过来之后,再通过session的id在高速缓存进行查询。相当于把Session持久化在高速缓存。由于动静分离版存在很大安全性问题,所以使用Nginx来接收Https请求,再通过Nginx将Https请求转换为Http请求。通过Nginx转换为普通的Http请求来传输到应用服务器之中,有效的提高了一定的安全性。但是由于缓存版中大量使用高速缓存,数据库和高速缓存之间没有同步机制,如果在查询高速缓存的时候,数据库有更新,而没有及时更新到高速缓存之中,那么用户查询到的结果还是之前的结果,就会存在一致性的问题。第二个问题是缓存失效的问题,由于缓存不能像数据库一样永久的持久化数据,当我们写一个数据到缓存的时候,都会设置一个超时的时间,当缓存失效了之后,大量用户再做查询时,会导致数据库崩溃。
特点
- 大量使用缓存
- Nginx接收Https
- Session持久化
- 存在一致性问题
- 存在缓存失效问题
2.3.4 分布式服务
分布式服务架构,保证功能不变的情况下,将应用拆分成前端web应用和后端服务,后端服务又根据服务的不同拆分多个子应用,共同提供服务,web应用调用这些服务来和用户打交道。这样web应用就不会包含太多底层的功能,将不同的服务封装起来,组成一个业务逻辑。web如何调用另外一台机器上的服务,这时候就要使用到分布式服务框架,或者企业服务总线等来将其它机器提供的服务通过远程调用来访问这些服务。例如分布式框架dubbo。都可以提供服务路由负载均衡调用统计等一些功能。更方便管理整个集群上的服务。拆分之后,应用的数量会增加很多,每个应用的负载相应的就会没有之前那么高。这时候我们需要对之前用来部署web应用的小型机来进行虚拟化,简单来将就是在小型机上,安装若干个虚拟机,将服务器部署在虚拟机之中,或者也可以将应用部署再云服务器中。分布式服务大量使用了第三方的中间件,比如消息中间件、调度中间件、监控平台。使用消息中间件可以将大量的异步操作发送到消息中间件之中,后台服务均匀的消费这些消息,避免了访问时的峰值对于整个数据库的压力的影响。同时拆分了异步的操作能够提升服务的吞吐量,避免大量耗时的操作影响用户。同时还增加了数据库的读写分离,配置多个读库来和主库同步,将所有的查询都映射到读库上,避免了数据库写入时对读取数据造成影响。设置读库还有一个好处就是能再主库挂掉的情况下,进行读写切换,瞬间将读库切换成主库,使得正常的业务部受影响。但是服务器的增多,第三方中间件的部署以及数据库组重等等,比之前增加许多需要监控的机器。对于服务器的部署必须能够自动化的运行,而且必须能够对应用实时监控,在应用发生异常之后,能够及时的通知这一系列的事情都极大的增加了运维的难度。但分布式服务版相当于缓存版能够将业务拆分,使得整个企业架构更加明晰,同时使用了消息中间件等等中间件,使得应用的吞吐量得到极大的提升,分布式服务版的瓶颈在于如果出现高并发的时候,对于某些应用的压力会非常大,而某台虚拟机的负载就会非常高,有可能导致整个小型机都受到影响。为了更好的负载压力和均匀的分配服务器的资源,于是就产生了弹性计算。
2.3.5 弹性计算
简单来说就是不需要去部署分配多台虚拟机,而是采用Docker这种容器级虚拟化,将应用部署在Docker容器中。容器级的虚拟化可以理解为就像web应用部署在tomcat之中一样,使用容器级的虚拟化,可以使得服务器资源能够实时分配。假设一个场景,在监控到web应用的压力负载增加到70%以上的时候,使用脚本能够新增一系列的docker容器,再将应用启动起来,这些操作能在秒级的情况下瞬间增加服务器资源来满足负载,当负载下降的时候,就停止应用,将docker容器也停止,能够节省服务器的资源来给其它服务使用。弹性计算本新增了Hadoop日志搜集平台,在应用产生应用日志之后,将日志写入Hadoop集群。不用再担心日志在docker容器停止之后造成丢失,同时能够更方便的对集群的日志做查询。同样Hadoop在处理离线资源的时候,一般是在晚上,那么这个时候应用的负载都很低,可以空出很多服务器的资源,我们在Hadoop任务之前,可以使用docker新增很多节点,再来进行计算,高效的利用了服务器的资源,同时基于docker容器还有一个好处就是能够很快的复制节点,在某部分机房有问题的时候,能够快速的在另外一个机房复制出大量应用,高效解决了异地容灾的问题。这个版本的数据库的使用和分布式服务有很大的区别,分布式服务只是利用了数据库的复制机制来做读写分离,而弹性计算不再和数据库直接打交道,而是使用了数据库中间件。对于开发来说,不需要在配置读写分离,而只是配置和中间件的连接,由数据库中间件来路由表,包括单表被水平拆分之后,使用数据库中间件来做集合或者是路由到具体的表中,将数据库的管理和应用开发人员隔离开来,更加简化了应用对数据库的操作。开发人员不再担心由于数据量的增加对数据库的压力,同时中间件还能配置将数据库的数据同步到Hadoop集群之中,再配置一些离线任务使用Hadoop来计算,计算的结果保存到Hadoop之中,再用中间件去读取Hadoop的计算结果,再写入到数据库。使用中间件来对数据库的数据源进行处理生成更高效的数据,来节省数据库的资源。
3常见的服务治理的方式
3.1 多域名分配
- 每个应用专属域名
- Http做进程通信
- 硬件负载或者Nginx
- 多语言
- 安全性较低
- 无法编辑检查
3.2 企业服务总线
- 支持多种方式路由以及注册
- 工作流的集成
- 高效、容易维护
- 过度依赖于中心
- 软件成本高
3.3 分布式服务框架
- 无中心也可以工作
- 基于接口编译检查
- Java环境中开发学习成本低
- 高效、高可用
- 多语言支持不足