微服务基础篇
- 1: service consumer -> Proxy Server ->Load Balance -> Service Discovery -> Target Service
- 2: Broser curl Other -> Zuul -> Ribbon -> Euraka -> Restful API
- zuul: 是边缘服务,用来提供动态路由,监控,授权,安全,调度等功能,将权限控制等一些业务逻辑抽离出来,单独放到Zuul里,使得服务组件更简单,具有更好的复用性.
- Zuul还负责将请求路由到服务上,起到了前台接待人员的作用,负责访客接待,当然也可以不使用zuul,
这时请求直接与后台的服务交互,但是这样破坏了接口原则,相当于不要前台人员直接去公司里面找人 - zuul是反向代理工具,类似的还有Nginx,
区别:
正向代理 代理的是客户端,反向代理代理的是服务端
正向代理: 服务端不知道客户端是谁.
反向代理: 客户端不知道服务端是谁.
- Ribbon 维护了一个服务列表,如果实例注销,ribbon能够自行将其剔除,但是如果该服务实例重新启动或者增加实例,需要手工调用Ribbon的接口吧服务加进Ribbon的服务列表.
这个工作还是交给euraka好了,所以一般二者结合使用.
客户端负载均衡: 具体来说是通过采取某种策略为客户端选择一个服务端,从而能够减少对服务端的压力,达到均衡负载的效果
- Feign: 是一个组件也是一个webservice客户端,用户服务之间调用.
- 微服务之间的通信有同步和异步: 同步的方式有: Rest,SOAP,RPC ,其中 Rest是面向资源的,SAOP的面向方法的,RPC是面向接口的.
Rest的主要特点: 每个资源都有一个ID,链接资源在一起,使用标准方法,资源多重描述,无状态通信, 优势: 易开发已维护,使用RPC的话,需要调用接口方法,代码上有渗透.
AXIS,CXF都会根据WSDL文件生成客户端代码,调用时代码耦合很多第三方代码
- Kafka: 来自LinkedIn之后成为Apache的一部分,Kafka本身是一个基于分布式系统,具有快速,可扩展,高性能,低耦合,高可靠性,数据不丢失等优点,
相比于传统消息系统有:(1)基于分布式(2)可同时为发布和订阅提供高吞吐量(3)支持多订阅者,当失败时能自动平衡消费者(4)将消息持久化到磁盘,因此可用于批量消费,如ETL以及实时应用等
系统架构:
- Broker:Kafka集群包含一个或多个服务器,这些服务器被称为Broker
Topic: 集群上有很多Topic,每个topic代表一类消息,所有发布到集群上的消息都会进入到属于自己的那个topic中,等待被处理
Partition:在物理存储上,每个topic包含一个或多个patition,创建topic时刻指定partition的数量,每个partition对应于一个文件夹,该文件夹下存储该partition的数据和索引文件.
Producer: 负责发布消息到Kafaka broker
Consumer: 消息消费者,负责从kafka broker读取消息进行处理.
Consumer Group: 每个消费者都属于一个特定的Consumer Group,没有就是默认组.
1: spring aop 的实现:
(1):对java字节码进行重新编译,将切面插入字节码的某些点和面上,可以是使用cglib库来实现
(2)制定类加载器,在类加载时对字节码进行补充,在字节码中插入切面,增加了除业务逻辑之外的功能,JVM 自身提供的Java Agent机制就是在加载类的字节码时,通过增加切面来实现AOP的
(3)JVM本身提供了动态代理组件,可以通过它实现任意对象的代理模式,在代理的过程中可以加入切面的逻辑,例如使用java提供的API Proxy.newistance()和InvocationHandler来实现.
(4)AspectJ是实现AOP的专业框架和平台.通过它可以实现任意方式的字节码切面.
2: Web Service: 每个服务都是对等的,并且互相是解耦的,通过WSDL定义的WSDL定义的服务发现接口进行访问,并通过SOAP协议进行通信.SOAP协议通常是一种在 http/https通道上传输xml数据来实现的协议, 但是每个服务都要依赖中心化的web service目录来发现现存的服务. xml数据在高并发网络传输中带来性能影响,后来被JSON取代.
3: ESB: 企业服务总线,是用于设计和实现网络服务化交互和通信的软件模型,是SOA的另一种实现方式,主要用于企业信息化的集成服务场景中. Mule是企业服务总线的一个实现.
ESB也适用于 事件处理,数据转换,消息和事件异步队列顺序处理,安全和异常处理,协议转换和保证通信服务的质量等场景.
| 服务1 | 服务2 | 服务3 | 服务4
_
企业服务总线
__
数据库数据源 消息队列 大数据 ERP
特点: (1)ESB服务没有中心化的服务节点,每个服务都是通过总线交互ESB的功能和职责
:
(1) 监控和控制服务之间的消息路由
(2)控制可插拔的服务化的功能和版本
(3)解析服务之间的交互和通信的内容和格式
(4)通过组合服务,资源和消息处理器来统一编排业务需要的信息处理流程
(5)使用冗余来提供服务的备份能力.
Web service 的问题
:
(1) 依赖中心化的服务发现机制
(2)使用SOAP通信协议,通常使用XML格式来序列化通信数据,XML格式的数据冗余太大
(3)服务化管理和治理设施并不完善
ESB的问题
:
(1) 虽然是SOA的实现的一种方式,但是更多的是系统集成的便利性,
(2) 过重的整体服务,内部依然复杂.
微服务的交互模式:
(1) 读者容错模式
(Tolerate Reader):指微服务化中服务提供者和消费者之间如何对接口的改变进行容错. 服务提供者对外的接口的数据格式的改变,增加和删除,都会导致服务的消费者不能正常工作,在实现过程中不推荐使用严格校验策略,而是推荐使用宽松的校验策略,即使服务消费者拿到的消息报文发生了改变,程序也只需尽最大努力提出需要的数据,同时忽略不可识别的数据.只有在完全不能识别接收到的消息或者无法通过识别的信息继续进行处理流程时,才能抛出异常.
建议: 在服务接口的定义中,参数可以使用枚举值,在返回值的DTO数据中禁止使用枚举值,(枚举改变,反序列化会出异常)
(2) 消费者驱动契约模式
:是用来定义服务化之间交互接口改变的最佳规则.
(3)服务契约分为
: 提供者契约,消费者契约以及消费者驱动契约,他从期望与约束的角度描述了服务提供者与消费者之间的联动关系,
(4) 去数据共享模式
:与SOA服务化对比,微服务是去ESB总线,去中心化以及分布式.而SOA还是以ESB为核心实现遗留系统的集成,以及基于web service为标准实现的通用的面向服务的架构,在微服务领域,微服务之间的交互通过定义良好的接口来实现,不允许使用共享数据来实现.
- 有些方案使用缓存或者数据库作为两个微服务之间的纽带,在业务处理过程中,为了简单,前一个服务将中间结果存入数据库或者缓存,下一个服务从缓存或数据库中拿出数据继续处理.
-
这种方案的缺点
- 使得微服务之间除了接口契约还存在数据存储契约
- 上游的数据格式发生变化,可能导致下游的处理逻辑问题
- 多服务共享一个资源服务,对资源服务的运维难以划清职责和界限
- 在做双机房独立部署时,需要考虑服务和资源的路由情况,跨机房的服务调用不能使用独立的资源部署模式,因此难以实现服务自治
在微服务设计时,一定不要共享缓存和数据库等资源,也不要使用总线模式,服务之间的通信和交互只能依赖良好的接口,通常使用Restful 样式的API或者透明的RPC调用框架
(5) `微服务的分解和组合模式:通常是用领域的动词和名词来划分微服务的,例如:对于一个电商后台系统,可以分解为, 订单,商品,商品目录,库存,购物车,交易,支付,发票,物流等子系统.
(6) 组合微服务
:
- (1)服务代理模式: 他根据业务的需求选择调用后端的某个服务,在返回给使用端之前,代理可以对后端服务的输出进行加工,也可以直接把后端服务的返回结果返回给使用端.
- (2) 服务聚合模式:根据业务流程处理的需要,以一定的顺序调用依赖的多个微服务,对依赖的微服务返回数据进行组合,加工和转换,最后以一定的形式返回给使用方.这里被依赖的微服务都有自己的缓存和数据库,聚合服务本身可以有自己的数据存储,包括缓存和数据库等,也可以简单的聚合,不需要持久化任何数据.
- 聚合服务的好处: 三个独立子服务可以独立开发,变更和部署,聚合服务封装下层的业务处理服务,由三个独立的子服务完成数据持久化等工作.项目结构清晰,三个子结构可以复用.
- (3)服务串联模式:类似一个工作流,最前面的一个服务接受请求和响应使用方,再与后面的服务交互.通常服务串联之间的调用使用
同步的RESTFul风格的远程调用实现,一个请求占用一个线程,优先使用聚合模式
- (4) 服务分支模式: 是服务代理模式,服务聚合模式和服务串联模式相结合的产物.例如支付服务对应多种支付渠道,
- (5)服务异步消息模式: 前面所有的服务组合都是用同步的restful风格的同步调用实现,同步调用模式在调用过程中会阻塞线程,如果服务方一直没有返回,则消费方会一直阻塞,严重时会出现撑满县城次,出现雪崩效应.
建议在构建微服务架构系统时,通常会梳理核心系统的最小化服务集合,这些核心系统使用同步调用,而其他核心链路以外的服务可以使用异步消息队列异步化.
- (6)服务共享数据模式: 这其实是反模式,一下两者情况使用,
单元化架构
:一些平台固态出于对性能较高的要求,所以采用微服务将服务分拆,但是性能反而下降,可以让不同的服务共享一些资源例如缓存或数据库,甚至可以将缓存和数据库在物理上与微服务部署在一个物理机中,最大限度的减少网络通信带来的性能损耗,这种称为:单元化架构.二是遗留的整体服务,耦合度较高,分拆会出现数据一致性分问题
微服务的容错模式
-
1: 舱壁隔离模式:
- (1)微服务容器分组,例如支付平台的微服务,将每个节点的服务池分为三组:准生产环境()内侧使用,灰度环境(跑一些普通商户的流量)和生产环境(大部分生产流量和vip商户流量).
- (2)线程池隔离:一般将同一类功能划分在一个微服务中,尽量避免微服务过细而导致成本增加......
- (3)熔断模式:hystrix等等
- (4) 限流模式:服务的容量和性能是有限的,限流机制一般会控制访问并发量.方法
(1)计数器
:通过原子变量计算单位时间内的访问数量,如超出某个阈值,则拒绝后续的请求.下一秒要清零操作,可以使用单独一个线程每隔一秒清零.
(2)
令牌筒
:比较流行,他通过一个线程在单位时间内产生固定数量的令牌,然后把令牌放入队列,每次请求调用需要从筒中拿取一个令牌,拿到令牌才有资格执行请求调用,否则只能等待拿到令牌在执行或直接丢弃.
(3)信号量
:在应用层使用信号量-
(5): 失效转移模式:若在微服务中发生了熔断或限流,该如何处理被拒绝的请求呢?
- (1)采用快速失败策略,直接返回错误,让使用放知道错误后自行解决.
- (2) 是否有备份服务,如果有备份服务,则迅速切换到备份服务
- (3) 失败的服务有可能是某台机器有问题,而不是所有机器有问题,这种情况下适合使用failover策略,采用重试的方法来解决,但是这种方法要求服务提供者的服务实现了蜜等性
库的分类:
- (1) 一方库: 本服务在JVM进程内依赖的Jar包
- (2) 二方库: 在服务外通过网络通信或者RPC调用的服务的Jar包
- (3) 三方库: 所依赖的其他公司或者组织提供的服务或者模块.
Java 微服务项目的层级结构:
服务导出层(war)[web.xml,spring环境] -> 服务接口层(Jar)[业务接口,DTO,枚举类] -> 服务实现层(Jar)[业务实现类,外部服务包装类,DAO]
注意这里有一个反模式: 永远不要在本地事物中调用远程服务,如果远程服务出了问题,则会拖长事物,导致应用服务器占用太多的数据库链接,让服务器负载迅速攀升,或拖垮数据库,
RPC框架的比较:
-
1: RMI: jdk1.4开始就内置了远程服务调用的技术栈,一个Java进程内的服务可以调用其他Java进程内的服务,使用JDK的序列化和反序列化协议.RMI是JEE规范中EJB远程调用的基础,然后RMI没有广泛应用,原因如下:
- (1): RMI采用JDK自带的序列化和反序列化协议,不能跨语言
- (2):使用了底层的网络协议,不如基于文本的HTTP可读,也不如HTTP被广泛认知和应用
- (3):开源框架的流行,严重消弱了JDK资深技术的流行程度
-
2: Hessian 和 Burlap:
- (1) Hessain:将对象序列化为语言无关的二进制协议,而Burlap将对象序列化成与语言无关的xml数据,数据是可读,两者都是与语言无关,可以在多种语言的服务中互相调用
- (2)Hessian 和 Burlap都适合传输小的对象, 对较大,复杂的对象,无论是在序列化方式还是传输通道上都没有RMI有优势.
- (3)由于服务化架构中的大量服务调用都是大规模,高并发的短小请求,因此Hessian 和Burlap协议在服务化架构中得到了广泛使用.
- 3: Spring Http Invoker: 重用了JDK内置的对象序列化技术传输对象,这与RMI原理是一样的.但是他通过HTTP通道传输数据,在效率上低于RMI,并且使用了内置的JDK序列化机制,因此也是不能跨语言的.