从单体到集群拆分到微服务【一】

  • A+
所属分类:.NET技术
摘要

这是我们最初的一个系统架构:无论我们是什么样的一个客户端,UI呈现是一个什么样的,后端都只有一个,相对比较简单;


1、单体架构:

这是我们最初的一个系统架构:无论我们是什么样的一个客户端,UI呈现是一个什么样的,后端都只有一个,相对比较简单;

                          从单体到集群拆分到微服务【一】

以前项目就一个进程,各种模块项目都放在一起,随着业务的发展,数据量,流量的不断增长,单体不够用了,【eg:一个石头太大,搬不动】那我们怎么做呢?

  • 要么换大力士【升级硬件】:but:升级硬件也是有上限的;
  • 要么多个人来搬,常见的2种方式有:
  1. 垂直拆分
  2. 水平

那什么是垂直呢?什么是水平呢?

A:垂直:也就是系统拆分,按系统业务、逻辑拆分成多个合作完成。

                 一个人搞不完的事,按系统业务拆分,一个人干一部分,把事情干完;              

                     从单体到集群拆分到微服务【一】

       但是:垂直也有一定的局限性,拆分多了,就比较碎片化,不仅不利用管理,单一节点压力还是会很大;

B:水平:也就是我们平时说的集群负载均衡

                    以前这个逻辑一个实例处理的,现在换成多个实例,干相同的事,换成多个实例,请求来了该找谁呢?这时候我们就用到了负载均衡,搭载Nginx做转发处理

                   一个人搞不定,那我们都多来几个干相同的事,请求来了,分发一下,把所有的事干了

                  扩展:Nginx-->高性能的Http和反向代理web服务器;工作原理:作为反向代理,请求之后,配置策略,根据策略把请求转发出去;

                  从单体到集群拆分到微服务【一】

  事实上,它们做的事都是一样的,都是都是想办法用有限的服务器,计算资源来处理原始的请求,以应对满足高并发,大数据的一些诉求;

  现在有3个服务实例,它们都要写log,那么我们不可能每个都写,这样就会重复构建,共同的东西,就可以把它抽出来,服务共享,也就是代码复用

  假如一个项目有100个功能点,按照2:8原则来分配,只有20%的业务是常用的,它们会承担80%的流量,而80%是一个进程,那个点的资源是所有程序共享的,就会划不来,那我们把20%的高频服务拆分出来,服务共享,独立的部分增加计算资源,多分一些资源,其它少一点,这样才能资源最大化利用;

                 从单体到集群拆分到微服务【一】

2、分布式

       如果在项目架构之间,多个项目,把一些操作,逻辑,业务或者服务独立出来,当作服务来共享调用,一次请求就变为:我调用A,A调用logserver,那么这样下来我们就来了一个新的名词,叫:分布式

       分布式:多进程协助完成业务;

A:分布式的代价:

    那么分布式有那么好么?eg:有一个词叫“欲戴皇冠,必成其重”,eg:分布式锁,分布式事务,以及它的复杂性..........;

     分布式锁:一个东西,最多一个人处理,2个人同时操作就会出问题,那么我们就要做一些进程上的互斥;

     分布式事务:你操作成功了,我操作失败了,所以我们就要来做些操作。来保证数据的一致性;

     为什么那么麻烦,我们还要使用它?好处:独立运维,独立扩展,独立部署【享受自己单独的硬件资源】,更好的利用资源;

3.微服务架构(Microsercice Architecture)

    随着时间的推移,业务倒逼技术不断的发展,分布式的问题都解决了,那么分布式就变成了常规手段,推演下午就变成了微服务;

    A.定义:

   微服务架构就是一个用分布式服务拆分业务逻辑,完成解耦的架构模式(架构风格)。

   B:究竟怎么拆分微服务?

  eg:三层架构里面有一层,DLL业务逻辑层----UI负责调用

   微服务---业务逻辑都放在服务里面---UI客户端负责调用,该集群集群,该部署部署,该运维运维,该注册发现,该网关网关,各种东西佩奇,就变成了微服务

  那么真如我们描述的这么简单么?

  以前我们调用BLL,在一个进程里,成功或者失败,结果一目了然,清清楚楚,那么我们变为了微服务,调用服务慢,或者失败,原因可能是代码,网络丢包,抖动,服务器,数据库挂了,超时等一系列可能性问题

  从单进程变为分布式,一切都不一样了

 

3.微服务架构全组件解析

  把方法都拆成独立服务了,怎么样保证项目是可用的呢?

   1.保证服务的高可用;

   2.服务的可伸缩性;

    A.核心基础:高可用

    从单体到集群拆分到微服务【一】

问题:风险太大--串行结构,任意节点出问题,全流程奔溃,这是项目的高压线,如果一个服务的可用性是99%,那2个,3个...7个,8个呢?简直不敢想象后果,充分体现了可用性的重要性

那我们怎么去保证可用性:答案是集群【可以理解为找备胎?】   

      从单体到集群拆分到微服务【一】

Nginx+KeepAlived做IP漂移,我们用nginx作反向代理负载均衡,通过nginx将客户端请求用轮询方式发送给服务器,我们部署了的一个nginx挂了怎么办 ?那我们就部署两个,使用keepalived监控nginx的健康状态,当nginx出现宕机时自动主备切换,实现IP漂移,来实现高可用

B.伸缩性:

总有服务是应对多个客户端的,我们的系统也会在不同的时段,出现压力不均的情况,甚至突然间压力变大10,100倍就会导致我们系统的奔溃,那问题来了,怎么办呢?我们总不可能在事先准备100份冗余资源吧。

我们的预期目标是希望它能自动伸缩,随着压力情况,自动开启新节点或者关闭节点。(Docker+swarm,或者K8S)

        从单体到集群拆分到微服务【一】

 游离在外面,请求过不去,怎么纳入集群里面管理起来使用?

 Nginx其自身的属性:可以自动减少,减少时会自动重启Nginx,如果新增节点则不能实现自动扩张,修改配置重启Nginx服务那现在怎么办?

 1.注册发现 

          从单体到集群拆分到微服务【一】

   那如果新增一个呢?

    从单体到集群拆分到微服务【一】 

   节点删除  

        从单体到集群拆分到微服务【一】

   如果满足了这个特性,就做到了自动伸缩,ConSul就完成了,我们的架构也就演变为:

      从单体到集群拆分到微服务【一】

  GRPC:局域网内部传输具有更高的性能,外部我们还是使用.core webapi

   问题:

   1.服务暴露:这么多服务实例可见,这么多端口暴露在外面还是会很危险;

   2.负载均衡;

   3.调用服务的麻烦;

   新增一个网关,通过包一层的方式去解决上面的问题,由网关GeteWay去处理,做的事跟Nginx差不多;

   它们的区别:Nginx是一个单独的服务器,要扩展需要写Lua脚本,但网关还要很多额外功能;

   2.网关Gateway

   网关用Ocelot,Kong,推荐用Ocelot,[c#写的方便扩展,微软出品]

      从单体到集群拆分到微服务【一】 

   从图中可以看出网关是一切网络的出入口,这样显得它在整个架构中尤为重要,那我们就要考虑到它的可用性,一个挂了,整个流程都结束了,那我们就集群呗;

     从单体到集群拆分到微服务【一】

   集群完,这么多网关怎么访问,难道我记4个地址吗?去调用哪一个呢?

        从单体到集群拆分到微服务【一】

    问题:网关调用服务实例,还是要担心服务挂了,服务超时的问题,所以这个地方网关除了去做服务注册,转发,还要去做路由映射,,,,,

   没有网关的请求:

                     从单体到集群拆分到微服务【一】

  加了网关的请求:

                  从单体到集群拆分到微服务【一】

    有了网关,就可以把关系整理清晰

    请求超时:

        从单体到集群拆分到微服务【一】

     雪崩:在串行化链路里面,任意节点的故障都会导致整个链路的崩溃。那怎么处理这个问题呢?:

    限时解决:定义1S的请求,>1s,不管你是否成功,我都不会再管这个结果,认为Fail,虽然这中间有一个失败了,但是保证了整个链路的健康状态  

   限流:

   从单体到集群拆分到微服务【一】

熔断,降级等等

    从单体到集群拆分到微服务【一】

  最后除了以上这些,还有鉴权,授权

    从单体到集群拆分到微服务【一】

   加了鉴权授权,请求的时候,带上Token,有权限就请求,没权限只能出门左转回家

   到这,核心模型就搭建完成了

  问题思考:那么我们如何拆分才能保证系统高内聚,低耦合?