037 关于微服务的认识

  对于微服务,还是只是一个感性的理解,缺乏系统的整理。

  而且,读每一篇文章,都感觉有道理。这样就需要,先将人家比较好的文档列举,然后整理出自己文档。

一:一个简单的普通的理解,不涉及具体的技术

  一、什么是微服务?
  微服务架构风格是一种讲一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制,这些服务围绕业务能力构建并且可通过全自动部署机制独立部署,这些服务公用一个小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储。
  微服务具备以下的特性:

    每个微服务可独立运行在自己的进程里
    一系列独立运行的微服务共同构建起整个系统
    每个微服务为独立的业务开发,一个微服务只关注某个特定的功能
    微服务之间通过一些轻量级的通信机制进行通信
    可以使用不同的语言和数据存储技术
    全自动部署机制
  二、微服务的优点
    易于维护和开发:一个微服务只关注一个特定的业务功能,所以它业务清晰,代码量较少,开发和维护单个微服务相对简单
    单个微服务启动较快:单个微服务代码量少,所以启动较快
    局部修改容易部署
    技术栈不受限:在微服务架构中,可以结合项目业务及团队的特点合理的选择技术栈
    按需伸缩:可根据需求实现细粒度的扩展
  三、微服务面对的挑战
    运维要求较高:更多的服务以为者更多的运维投入
    分布式固有的复杂性:使用微服务构建的是分布式系统,对于一个分布式系统,系统容错,网络延迟,分布式事物都会带来巨大的挑战
    接口调整成本高:微服务之间通过接口进行通信,如果修改某一个微服务的API,可能所有使用该接口的微服务都需要调整
    重复劳动:很多微服务都会使用到相同的功能,而这个功能还没有达到分解为一个微服务的程度,这个时候,可能各个服务会开发这一个功能而导致代码重复
  四、微服务设计的原则
    单一职责原则:单一职责是指一个单元(类,方法或者服务等)只应关注整个系统功能中单独有界限的一部分
    服务自治原则:服务自治原则是指每个微服务应具备独立的业务能力,依赖与运行环境
    轻量级通信原则:微服务之间应该通过轻量级的通信机制进行交互
    微服务粒度划分合理:微服务粒度是难点,应当使用合理的粒度划分微服务问不是一味的把服务做小,代码量的多少并不能作为微服务划分的依据,因为不同的微服务本身业务的复杂性不同,代码量也不同
  ---------------------
    作者:zhao_double_huan
    来源:CSDN
    原文:https://blog.csdn.net/weixin_41098980/article/details/79826986?utm_source=copy
    版权声明:本文为博主原创文章,转载请附上博文链接!

二:详细的微服务知识点

1.微服务的由来

     微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。

2.单体带来的问题

    单体架构在规模比较小的情况下工作情况良好,但是随着系统规模的扩大,它暴露出来的问题也越来越多,主要有以下几点:

  1.复杂性逐渐变高

  • 比如有的项目有几十万行代码,各个模块之间区别比较模糊,逻辑比较混乱,代码越多复杂性越高,越难解决遇到的问题。

  2.技术债务逐渐上升

  • 公司的人员流动是再正常不过的事情,有的员工在离职之前,疏于代码质量的自我管束,导致留下来很多坑,由于单体项目代码量庞大的惊人,留下的坑很难被发觉,这就给新来的员工带来很大的烦恼,人员流动越大所留下的坑越多,也就是所谓的技术债务越来越多。

  3.部署速度逐渐变慢

  • 这个就很好理解了,单体架构模块非常多,代码量非常庞大,导致部署项目所花费的时间越来越多,曾经有的项目启动就要一二十分钟,这是多么恐怖的事情啊,启动几次项目一天的时间就过去了,留给开发者开发的时间就非常少了。

  4.阻碍技术创新

  • 比如以前的某个项目使用struts2写的,由于各个模块之间有着千丝万缕的联系,代码量大,逻辑不够清楚,如果现在想用spring mvc来重构这个项目将是非常困难的,付出的成本将非常大,所以更多的时候公司不得不硬着头皮继续使用老的struts架构,这就阻碍了技术的创新。

  5.无法按需伸缩

  • 比如说电影模块是CPU密集型的模块,而订单模块是IO密集型的模块,假如我们要提升订单模块的性能,比如加大内存、增加硬盘,但是由于所有的模块都在一个架构下,因此我们在扩展订单模块的性能时不得不考虑其它模块的因素,因为我们不能因为扩展某个模块的性能而损害其它模块的性能,从而无法按需进行伸缩。

3.微服务与单体的区别

  1. 单体架构所有的模块全都耦合在一块,代码量大,维护困难,微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。

  2. 单体架构所有的模块都共用一个数据库,存储方式比较单一,微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。

  3. 单体架构所有的模块开发所使用的技术一样,微服务每个模块都可以使用不同的开发技术,开发模式更灵活。

4.微服务与SOA

  微服务,从本质意义上看,还是 SOA 架构。但内涵有所不同,微服务并不绑定某种特殊的技术,在一个微服务的系统中,可以有 Java 编写的服务,也可以有 Python编写的服务,他们是靠Restful架构风格统一成一个系统的。所以微服务本身与具体技术实现无关,扩展性强。

5.微服务的目的

  微服务的目的是有效的拆分应用,实现敏捷开发和部署 。

6.什么样的项目适合使用微服务

   微服务可以按照业务功能本身的独立性来划分,如果系统提供的业务是非常底层的,如:操作系统内核、存储系统、网络系统、数据库系统等等,这类系统都偏底层,功能和功能之间有着紧密的配合关系,如果强制拆分为较小的服务单元,会让集成工作量急剧上升,并且这种人为的切割无法带来业务上的真正的隔离,所以无法做到独立部署和运行,也就不适合做成微服务了。

  能不能做成微服务,取决于四个要素:

  • 小:微服务体积小,2 pizza 团队。

  • 独:能够独立的部署和运行。

  • 轻:使用轻量级的通信机制和架构。

  • 松:为服务之间是松耦合的。

7.微服务的拆分与设计

  1. 从单体式结构转向微服务架构中会持续碰到服务边界划分的问题:比如,我们有user 服务来提供用户的基础信息,那么用户的头像和图片等是应该单独划分为一个新的service更好还是应该合并到user服务里呢?如果服务的粒度划分的过粗,那就回到了单体式的老路;如果过细,那服务间调用的开销就变得不可忽视了,管理难度也会指数级增加。目前为止还没有一个可以称之为服务边界划分的标准,只能根据不同的业务系统加以调节

  2. 拆分的大原则是当一块业务不依赖或极少依赖其它服务,有独立的业务语义,为超过2个的其他服务或客户端提供数据,那么它就应该被拆分成一个独立的服务模块。

8.特征

  1. 每个微服务可独立运行在自己的进程里;

  2. 一系列独立运行的微服务共同构建起了整个系统;

  3. 每个服务为独立的业务开发,一个微服务一般完成某个特定的功能,比如:订单管理,用户管理等;

  4. 微服务之间通过一些轻量级的通信机制进行通信,例如通过REST API或者RPC的方式进行调用。

9.优点与缺点(上文说过,这里更加详细的诠释)

  易于开发和维护

  • 由于微服务单个模块就相当于一个项目,开发这个模块我们就只需关心这个模块的逻辑即可,代码量和逻辑复杂度都会降低,从而易于开发和维护。

  启动较快

  • 这是相对单个微服务来讲的,相比于启动单体架构的整个项目,启动某个模块的服务速度明显是要快很多的。

  局部修改容易部署

  • 在开发中发现了一个问题,如果是单体架构的话,我们就需要重新发布并启动整个项目,非常耗时间,但是微服务则不同,哪个模块出现了bug我们只需要解决那个模块的bug就可以了,解决完bug之后,我们只需要重启这个模块的服务即可,部署相对简单,不必重启整个项目从而大大节约时间。

  技术栈不受限

  •   比如订单微服务和电影微服务原来都是用java写的,现在我们想把电影微服务改成nodeJs技术,这是完全可以的,而且由于所关注的只是电影的逻辑而已,因此技术更换的成本也就会少很多。

  按需伸缩

  • 我们上面说了单体架构在想扩展某个模块的性能时不得不考虑到其它模块的性能会不会受影响,对于我们微服务来讲,完全不是问题,电影模块通过什么方式来提升性能不必考虑其它模块的情况。

  缺点

  运维要求较高

  • 对于单体架构来讲,我们只需要维护好这一个项目就可以了,但是对于微服务架构来讲,由于项目是由多个微服务构成的,每个模块出现问题都会造成整个项目运行出现异常,想要知道是哪个模块造成的问题往往是不容易的,因为我们无法一步一步通过debug的方式来跟踪,这就对运维人员提出了很高的要求。

  分布式的复杂性

  • 对于单体架构来讲,我们可以不使用分布式,但是对于微服务架构来说,分布式几乎是必会用的技术,由于分布式本身的复杂性,导致微服务架构也变得复杂起来。

  接口调整成本高

  • 比如,用户微服务是要被订单微服务和电影微服务所调用的,一旦用户微服务的接口发生大的变动,那么所有依赖它的微服务都要做相应的调整,由于微服务可能非常多,那么调整接口所造成的成本将会明显提高。

  重复劳动

  • 对于单体架构来讲,如果某段业务被多个模块所共同使用,我们便可以抽象成一个工具类,被所有模块直接调用,但是微服务却无法这样做,因为这个微服务的工具类是不能被其它微服务所直接调用的,从而我们便不得不在每个微服务上都建这么一个工具类,从而导致代码的重复。

10.微服务框架

  1. Spring Cloud:http://projects.spring.io/spring-cloud(现在非常流行的微服务架构)

  2. Dubbo:http://dubbo.io

  3. Dropwizard:http://www.dropwizard.io (关注单个微服务的开发)

  4. Consul、etcd&etc.(微服务的模块)

11.Spring Boot 与Spring Cloud

  Spring Boot:

    旨在简化创建产品级的Spring应用和服务,简化了配置文件,使用嵌入式web服务器,含有诸多开箱即用微服务功能,可以和spring cloud联合部署。

   Spring Cloud:

    微服务工具包,为开发者提供了在分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等开发工具包。

12.客户端访问服务

  一般在后台N个服务和UI之间一般会一个代理或者叫API Gateway,他的作用包括

  • 提供统一服务入口,让微服务对前台透明

  • 聚合后台的服务,节省流量,提升性能

  • 提供安全,过滤,流控等API管理功能

13.服务之间进行通信

  • REST(JAX-RS,Spring Boot)

  • RPC(Thrift, Dubbo)

  • 异步消息调用(Kafka, Notify)

  一般同步调用比较简单,一致性强,但是容易出调用问题,性能体验上也会差些,特别是调用层次多的时候。RESTful和RPC的比较也是一个很有意 思的话题。一般REST基于HTTP,更容易实现,更容易被接受,服务端实现技术也更灵活些,各个语言都能支持,同时能跨客户端,对客户端没有特殊的要 求,只要封装了HTTP的SDK就能调用,所以相对使用的广一些。RPC也有自己的优点,传输协议更高效,安全更可控,特别在一个公司内部,如果有统一个的开发规范和统一的服务框架时,他的开发效率优势更明显些。就看各自的技术积累实际条件,自己的选择了。

  而异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方,同时能 保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据最终一致性;还有就是后台服务一般要 实现幂等性,因为消息发送出于性能的考虑一般会有重复(保证消息的被收到且仅收到一次对性能是很大的考验);最后就是必须引入一个独立的broker,如 果公司内部没有技术积累,对broker分布式管理也是一个很大的挑战。

14.服务发现

  在微服务架构中,一般每一个服务都是有多个拷贝,来做负载均衡。一个服务随时可能下线,也可能应对临时访问压力增加新的服务节点。服务之间如何相互 感知?服务如何管理?这就是服务发现的问题了。一般有两类做法,也各有优缺点。基本都是通过zookeeper等类似技术做服务注册信息的分布式管理。当 服务上线时,服务提供者将自己的服务信息注册到ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息。服务调用者通过ZK寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK会发通知给服务客户端。

  客户端做:优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,一般大公司都有成熟的内部框架支持,比如Dubbo。 

  服务端做:优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多。

15.服务挂掉

  分布式最大的特性就是网络是不可靠 的。通过微服务拆分能降低这个风险,不过如果没有特别的保障,结局肯定是噩梦。我们刚遇到一个线上故障就是一个很不起眼的SQL计数功能,在访问量上升 时,导致数据库load彪高,影响了所在应用的性能,从而影响所有调用这个应用服务的前台应用。所以当我们的系统是由一系列的服务调用链组成的时候,我们必须确保任一环节出问题都不至于影响整体链路。相应的手段有很多:

  • 重试机制

  • 限流

  • 熔断机制

  • 负载均衡

  • 降级(本地缓存)

原文地址:https://www.cnblogs.com/juncaoit/p/9785449.html