基于SpringCloud的微服务架构设计

大家好,今天分享的是我最近在公司刚实现的一套微服务架构,用作于公司基础性服务(例如搜索,Passport Server,分布式任务调度系统等)

以下是整体架构

基于SpringCloud的微服务架构设计

可以看出,可以分为7个模块,整体是分层架构

  1. 反向代理层
  2. 网关层
  3. 服务层
  4. 存储层
  5. 服务治理中心
  6. 配置中心
  7. 消息总线

下面简单的介绍下这7个模块

1反向代理层:

         首先这个模块的的主要作用是为了对外屏蔽内部集群,常见实现有很多比如我用的最多的Nginx就是其中之一,但是这里我选择Zuul。

优势:

  1. SpringCloud对Zuul做了很全的集成,搭建各方面都很方便。
  2. Zuul在微服务架构中本身也属于一个微服务,好处就很明显了,我们可以通过治理中心全方位的监控服务状态
  3. 虽然性能方面Zuul需要一定的预热但是短时间预热后性能和Nginx基本相当

但是有些问题,我们都知道在微服务架构中所有服务均依赖于网关,而且整个架构中可能会有多个系统或者项目,那么网关的重要性就显而易见了,一旦网关挂了,那么整个集群对外就处于瘫痪状态了,这个问题我们称为单点故障,这是很恐怖的。

因为一个域名只能对应一个IP,一个IP可以对应多个域名的特性,我们不能通过单一的多开实例来解决这个问题了,因为最终域名特性决定了最终只能有一个出口。那么该怎么解决这个问题呢?

这里就要说到VRRP协议了,大致介绍一下,这是一个虚拟IP轻量级服务(虚拟路由器冗余协议),解决这个问题就是在传统服务主从的基础上,在每个服务实例所在的服务上建立虚拟IP并连接到Internet上,并对服务进行心跳检测。当服务出现问题后,它会将IP从当前服务中移到备份服务器上。这样就实现了代理层的高可用。由于VRRP实现本身是一个非常轻量的服务几乎可以不用担他会挂掉,而且用到他的时候一般是服务挂了。某种程度上可以说是一种解耦,将两种问题全部发生的概率降到了最低。

2 网关层:

这层的主要作用是为了解决跨域,业务复杂度等问题,就打个比方说登录认证,因为微服务架构下,所有一个服务所负责的功能很少,很多时候用户一个请求会同时调用多个服务,而这多个服务都需要在用户登录后才能操作,那么问题就很明显了,登录认证冗余了除了请求校验,当然还有其他的一些功能比如说请求过滤的等,这些网关都可以来处理。这里可能有人会问,请求过滤反向代理也可以做啊。这个问题问的好,从两个角度出发,一个是程序设计原则中有一个叫单一职责制。意思就是说一个实例只负责一个抽象上的功能,那么服务将网关一定业务相关的操作和反代结合到一起明显是不合适的。另外从流量上说,反代那层本身压力就很大了,我们要做的肯定是将他的实则单一化,性能最大化,这样就算出现了问题影响范围也会更小一些。

3 微服务层:

这层可以说是整个架构下业务最核心的地方了,以我的经验来看,在设计初期微服务的业务范围设定较考验开发人员的经验以及抽象能力。合理的规划微服务,也是微服务架构一大重点。

另外一点是这层中也一定要注意服务间的依赖关系,服务之间要有层次关系,下层服务不能调用上层服务,减少业务规模化后程序扩展,重构时的复杂度。已经循环依赖可能会导致的服务启动时的无限循环,导致服务无法启动等问题。

4 存储层:

这层就是数据存储了,在互联网环境下使用的种类也比较多。值得注意的是,在微服务下每个微服务只对应一个数据库。绝对不允许出现多个微服务使用同一个数据库,这样会增加服务间的耦合。

5 服务治理中心:

服务治理比较重要,可以说是整个微服务架构中最核心的部分了,主要是解决项目规模化后的一些静态配置难以维度等问题(例如 高可用的服务调用,负载均衡,服务降级等操作)

服务治理这里使用的是Eureka,为什么不用zookeeper呢?这里主要原因是因为他们两个的服务发现的机制不一样,这里就要说到著名的C(一致性)A(可用性)P(分区容错性)定理了。当数据同步时在相对时间刻度下服务间数据未达到一致,即为发生了分区情况,这时就要在一致性和可用性之间进行选取。可以看出来P是不可避免的。所以CAP定理中就说到分布式系统最多满足两个。

其中Eureka遵从的是AP原则,zookeeper是CP原则。之所以zookeeper不适用与服务发现功能主要原因就是因为zookeeper集群当leader发生故障后会进行leader竞选而这个时候,服务发现功能为了保证服务消费者获取到的服务列表是完全正确的,这时就会暂停服务发现,等选举完成后恢复正常,而选举往往会进行30s~120s很明显这对服务发现来说几乎是不能忍受的。一个是服务发现就性质来说本身变动性就相对较低,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接挂掉不可用。所以就服务发现来说zookeeper是不适用的。

相反Eureka遵从的是CP原则,更强调可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况: 
        1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 
        2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用) 
        3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

6 配置中心:

在服务规模化后,每个服务的配置不经相同,配置中心主要起到分环境配置以及配置中心化等功能

7消息总线:

构建一个所有服务共用的消息将所有微服务实例都连接起来,来做服务间沟通的一些功能,减少业务复杂度降低耦合。结合配置中心还能达到动态刷新配置等效果Spring Cloud中提供了Spring Cloud Bus实现消息总线。

总结:

微服务的兴起的确是顺应了发展,快速迭代,拥抱变化,轻量,成型后便于维护和扩展等优势。但也有些弊端,例如运维成本较高,服务划分对开发人员经验要求较高。由于彼此间服务沟通是通过RestFul协议进行的,网络消耗相对也会更高一些。所以在架构选型上还是需要一定的前瞻性的调研的。切记不要盲目的跟从潮流。

由于是刚完成还需要进一步测试和完善有些细节还未想好,所以还请大家多多提出自己的看法共同进步。本文章也会持续迭代