写点什么

微服务相关组件

作者:想要飞的猪
  • 2023-12-01
    广东
  • 本文字数:4350 字

    阅读完需:约 14 分钟

注册中心

管理服务(可以动态的添加和下线服务) nacos 会产生脑裂问题吗? AP 模式下是可以的,如 有三台 nacos 服务,leader Flollower1 Follower2 , 当 leader 无法与 follower 通信,Follower 之间可以通信时,则原来的 leader 会正常对外通信,但是 Follower 之间链接不到 leader 会触发选举,会产生新的 leader2,都会正常对外提供服务, 共享配置 与扩展配置,使用 share-config ,与 extentions-config,扩展的作用一般就是个性化的配置,需要覆盖共享配置的,所以扩展的优先级要高于共享的

负载均衡

负载均衡的意义在于合理利用资源,能够最大吞吐量,最小响应时间,并且避免单一资源的过载。

区域权衡策略:继承了两个过滤器,过滤掉链接超时 以及链接过多的服务器,过滤掉不符合的区域,然后在剩下的服务器中轮询。

随机策略:在所有的服务器中随机获取一个,获取不到则一直循环

轮询策略:轮询访问所有的服务器,如果获取不到则返回一个空 server

重试策略:继承了轮询,把获取到的 server 进行 null 与 alive 判断,在 500 毫秒内一直判断。

最小链接数:遍历所有的 serverlist,获取最小链接数的 server ,如果没有获取到则,进行轮询

可用性过滤:扩展了轮询策略,把获取到的 server 进行可用性判断。

服务调用

dubbo:

请求流程

1、provider(服务提供者)启动时把要提供的所有接口注册到注册中心,并订阅配置信息

2、consumer(服务消费者)启动时会去注册中心订阅自己需要的 provider,配置信息,router(路由); 3、当订阅消息有变更时注册中心会推送给消费者相关的服务提供者列表,配置信息,以及路由信息。 4、消费者发起请求时,会在服务列表中,根据客户端的负载均衡挑选一个服务进行请求,如果调用失败,则会选择另外的一台(默认重试两次,间隔为 0 ,也就是立即重试),

5、服务消费者与提供者,每个一分钟发送一次在内存中保存的调用次数与时间

openfeign:

feign 是一个 RESTFul 风格的 http 服务的客户端;是对 Ribbon 和 RestTemplate 的封装集成。使开发者不用手动调用 RestTemplate,只需要一个注解就可以实现,这样更符合过程调用。Openfeign 增加了对 SPringMVC 注解的支持。注意超时时间:由于 OpenFeign 集成了 Ribbon,如果没有设置 OpenFeign 的超时时间,则使用 Ribbon 超时时间,Ribbon 默认超时时间为 1 秒,OpenFeign 超时时间为链接 10s 读取 60s,所以一般推荐设置 OpenFeign 的超时时间(如果没有设置超时时间,则会使用 Ribbon 的超时时间)。

两者不同

1. 协议不同:Dubbo 支持多种协议(Dubbo,http,Rmi 等协议),Feign 一般用 HTTP 协议通信 2. 使用方式:Dubbo 更加底层,需要显示的定义接口与实现,并配置各种参数。OpenFeign 则更倾向于声明式编程,通过注解来实现。

3. 生态地位不同:Dubbo 是一个独立的 RPC 框架,它提供了完成的服务治理解决方案;OpenFeign 是 Springcluond 生态中的一部分,与其他组件紧密集成。

4. Dubbo 提供了丰富的功能,如:容错机制,负载均衡,服务注册等等,OpenFeign 则专注于 RESTFul 风格的接口调用。

配置中心

主要作用

集中管理配置,提高维护性,时效性、安全性。 如:很多微服务组件链接了 redis,当 redis 迁移时,如果配置是在本地则需要修改所有的服务组件的配置,并且需要重启服务,如果是在配置中心,则只需要修改配置中心的配置项,所有的都可以生效,并且不需要重启服务;

原理:服务端创建了相关的配置项之后,客户端就可以进行监听,客户端通过一个定时任务来检查自己监听的配置项数据是否发生改变(获取到服务端的文件与本地保存的文件 MD5 进行对比,如果不一致则表示发生了改变)。 文件服务端到 客户端有两种方式(推与拉): 拉的优势:实现简单,只需要客户端一个无状态的 http 请求,如果是使用推的方式,则服务端还需要维护每个客户端的信息,以及检测是否在线等一些情况,服务端压力比较大,拉的情况则由每个客户端分摊了压力,且不需要维护心跳。

服务熔断: hystrix 仓壁模式:每个 RPC 调用都是在一个线程池中获取线程,然后进行调用,如果多个服务使用同一个线程池,如果有某一个服务有故障,导致线程池中线程使用完,可能会产生雪崩效应,可以为每一个服务分配一个线程池(各自使用自己的线程池),在 HystrixCommon 的命令中可以设置,也可以根据 Group key 来公用。 服务熔断是应对雪崩效应的一种微服务链路保护机制,当某个微服务不可用或者响应时间太长是会进行服务降级,进而熔断该节点的服务调用,快速返回降级后的信息,当检测到该服务调用响应正常后恢复调用链路,Hystrix 的实现,当达到阈值时(默认 5 秒内 20)如果失败,则启动熔断机制。 服务降级:当调用服务超时时(@HystrixCommand(fallbackMethod=”XXX”) 一般默认是 1000 毫秒),执行一个兜底的方法。一般进行返回友好的错误提示。 设置 callback 方法:可以设置默认的方法,

sentinel 服务熔断:主要分为三个状态

1、熔断关闭状态 对请求不做限制

2、熔断开启状态 后续对该服务的接口调用不再经过网络,直接执行本地的 fallback 方法。 3、尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率,如果达到预期,则说明已经恢复,进入关闭状态,如果仍旧很低,则进入熔断关闭状态。

分布式事务

XA 协议是事务管理器与资源管理器之间通讯标准接口与协议。

1、两段提交 2PC:

1)、事务发起者想事务管理器 TM 发起一个事务,TM 建立分支事务,事务管理器(协调者)发起准备命令,等到所有的参与者返回后,根据返回的结果决定,提交还是回滚,

2)、发提交或者回滚命令(发起命令之后,会一直重试,直到所有参与者都完成,不然会阻塞) 2、三段提交/3PC

1)、准备阶段

2)、预提交

3)、提交、回滚阶段

解决了 2PC 在提交阶段,协调者与某参与者都挂了之后,新选举的协调者不知道怎么处理的情况,但是也不能确定参与者是否已经执行了命令 2PC 与 3PC 都不能保证 100%的一致 所以需要有一定的扫描补偿机制

3、TCC

分为三部分 try -->( confim、cancle)三阶段

TCC 组件(事务参与方):需要先注册到事务管理器

事务发起方:启动一个事务,事务管理器会先

1 、创建事务日志 —>2、批量调用 try 接口—>所有的 TCC 组件返回的结果 —>3、更新事务日志 —>4、 根据结果决定,执行 confim 还是 cancel 接口。

TCC 存在的问题

1. 业务入侵比较大

2. 开发成本高,对开发人员能力要求高

3. 空回滚(在没有执行 try 的情况下,执行 cancel 方法)

4. 幂等(可能会重复调用第二阶段【confim、cancel】)所以需要第二阶段幂等

5. 悬挂(执行完了第二阶段了才执行第一阶段)

空回滚与悬挂解决方案:

建立事务控制表,在事务表中记录状态, 在执行第二阶段时判断是否已经执行过第一阶段就不会有空回滚情况,在执行第一阶段时,判断是否执行过了第二阶段就不会有悬挂的情况

4、本地消息表

建立事务表与业务处于同一个本地事务,然后 A 再通过 MQ 发送给 B 端,进行事务,B 完成后再通知 A,进行修改事务状态(因为要写入消息表,如果高并发情况下,会有大量的 IO,所以不适用高并发的场景) 5、可靠消息最终一致性 利用 MQ 的事务消息,代替本地事务消息表。

服务网关

与业务无关的:

- 全局流量控制

- 日志统计

- 黑白名单

- 防止 SQL 注入

业务相关的:

- 权限校验

- 服务级别的流控

- 服务级别的降级

- 路由与负载均衡、灰度策略等

自定义路由断言工厂

1、必须是 spring 的 bean

2、必须使用 RoutePredicateFactory 结尾的类名称,前缀就是配置文件中的断言配置项,如 AfterRoutePredicateFactory 配置的文件中就只需要配置 - After

3、必须继承 AbstractRoutePredicateFactory 工厂

4、必须声明静态内部类 用于接收参数

5、经过 shortcutFieldOrder 进行绑定

6、apply 中编写断言逻辑



import java.time.LocalTime;import java.util.function.Predicate;
@Componentpublic class TimeOfDayRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeOfDayRoutePredicateFactory.Config> {
public TimeOfDayRoutePredicateFactory() { super(Config.class); }
@Override public List<String> shortcutFieldOrder() { return Arrays.asList("startTime", "endTime"); }
@Override public Predicate<ServerWebExchange> apply(Config config) { LocalTime startTime = LocalTime.parse(config.startTime); LocalTime endTime = LocalTime.parse(config.endTime);
return exchange -> { LocalTime now = LocalTime.now(); return now.isAfter(startTime) && now.isBefore(endTime); }; }
public static class Config { private String startTime; private String endTime;
public String getStartTime() { return startTime; }
public void setStartTime(String startTime) { this.startTime = startTime; }
public String getEndTime() { return endTime; }
public void setEndTime(String endTime) { this.endTime = endTime; } }}
复制代码


spring:  cloud:    gateway:      routes:        - id: time-based-route          uri: http://serviceA          predicates:            - TimeOfDay=startTime=08:00,endTime=18:00 
复制代码


自定义过滤器:与自定义断言相似,这是命名不同(GatewayFilterFactory) 继承的类不同, 全局过滤器不需要配置就会自动生效,自定义全局过滤器只需要实现 GlobalFilter

链路追踪

skyWaking: ZipKin+Sleuth:(请求 trace id 标识整个请求链路,Span ID 到达一个服务时,创建一个 span id,标识这个服务的开始与结束 就可以统计出单个服务耗费的时间)


用户头像

还未添加个人签名 2020-06-05 加入

还未添加个人简介

评论

发布
暂无评论
微服务相关组件_想要飞的猪_InfoQ写作社区