7.微服务架构
SpringCloud
01.Spring Cloud 有哪些组件
Spring Cloud Netflix ,它是 Netflix 公司基于它们自己的 Eureka、Hystrix、Zuul、 Ribbon 等组件,构建的一个 Spring Cloud 实现技术栈。 Spring Cloud Netflix 要进入维护模式,目前已经开始有新的基于 Spring Cloud 实现,可以作为新的选择。如下表格:
02.Spring Cloud 和 Spring Boot 的区别和关系
Spring Boot 专注于快速方便的开发单个个体微服务。 Spring Cloud 是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将 Spring Boot 开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线等的集成服务。 Spring Boot 可以离开 Spring Cloud 独立使用,但是 Spring Cloud 离不开 Spring Boot ,属于依赖的关系。 总结: Spring Boot ,专注于快速,方便的开发单个微服务个体。 Spring Cloud ,关注全局的服务治理框架。
03.什么是springcloud、springcloud的核心组件有哪些?
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统 基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控 等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它 只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再 封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系 统开发工具包 体系中的核心组件: 服务发现——Netflix Eureka 客服端负载均衡——Netflix Ribbon、OpenFeign 断路器——Netflix Hystrix 服务网关——Gateway 优点 产出于Spring大家族,Spring在企业级开发框架中无人能敌,来头很大,可以保证后续的更新、 完善 组件丰富,功能齐全。Spring Cloud 为微服务架构提供了非常完整的支持。例如、配置管理、服务发现、断路 器、微服务网关等; Spring Cloud 社区活跃度很高,教程很丰富,遇到问题很容易找到解决方案 服务拆分粒度更细,耦合度比较低,有利于资源重复利用,有利于提高开发效率 可以更精准的制定优化服务方案,提高系统的可维护性 减轻团队的成本,可以并行开发,不用关注其他人怎么开发,先关注自己的开发 微服务可以是跨平台的,可以用任何一种语言开发 适于互联网时代,产品迭代周期更短 缺点 微服务过多,治理成本高,不利于维护系统 分布式系统开发的成本高(容错,分布式事务等)对团队挑战大
04. springcloud与dubbo的区别有哪些
或许很多人会说Spring Cloud和Dubbo的对比有点不公平,Dubbo只是实现了服务治理,而Spring Cloud下面有33个子项目(可能还会新增)分别覆盖了微服务架构下的方方面面,服务治理只是其中的一 个方面,一定程度来说,Dubbo只是Spring Cloud Netflix中的一个子集。
05.springcloud服务如何在Eureka注册发现
更新机制包含删除和加载两个部分,上图黑色箭头表示删除缓存的动作,绿色表示加载或触发加载的动 作 删除二级缓存: Eureka Client发送register、renew 和 cancel 请求并更新 registry注册表之后,删除二级 缓存; Eureka Server 自身的 Evict Task 剔除服务后,删除二级缓存,二级缓存本身设置了 guava 的失效机制,隔一段时间后自己自动失效; 加载二级缓存: Eureka Client 发送 getRegistry 请求后,如果二级缓存中没有,就触发 guava 的 load,即 从 registry 中获取原始服务信息后进行处理加工,再加载到二级缓存中。Eureka Server 更新一 级缓存的时候,如果二级缓存没有数据,也会触发 guava 的 load。 更新一级缓存: Eureka Server 内置了一个 TimerTask,定时将二级缓存中的数据同步到一级缓存(这个动作包括了删除和加载
06.springcloud服务如何在nacos注册发现
首先阐述下nacos架构,如上图所示其中分为这么几个模块: Provider APP:服务提供者。 Consumer APP:服务消费者。 Name Server:通过Virtual IP或者DNS的方式实现Nacos高可用集群的服务路由。 Nacos Server:Nacos服务提供者。 Nacos Console:Nacos控制台。 nacos服务注册流程如下图所示: 服务实例启动时注册到服务注册表、关闭时则注销(服务注册)。 服务消费者可以通过查询服务注册表来获得可用的实例(服务发现)。 服务注册中心需要调用服务实例的健康检查API来验证其是否可以正确的处理请求(健康检查)。
07.ribbon负载均衡原理能简要的概述一下
LoadBalancerInterceptor:对负载服务的拦截处理 LoadBalancerClient:执行目标请求接口定义 RibbonLoadBalancerClient:是LoadBalancerClient的实现 ILoadBalancer:定义服务节点信息 public interface ILoadBalancer { void addServers(List var1); // 初始化服务列表 Server chooseServer(Object var1); // 从列表中选择一个服务 void markServerDown(Server var1); // 标记服务为down List getReachableServers(); // 获取up和reachable的服务 List getAllServers(); //获取所有服务(reachable and unreachable) } IRule:负载均衡策略接口 IPing:服务是否活跃
08.ribbon负载均衡策略有哪些简要概述一下
Ribbon作为后端负载均衡器,比Nginx更注重的是承担并发而不是请求分发,可以直接感知后台动态变 化来指定分发策略。它一共提供了7种负载均衡策略: BestAvailableRule:选择一个最小的并发请求的server AvailabilityFilteringRule:过滤掉那些因为一直连接失败的被标记为circuit tripped的后 端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) WeightedResponseTimeRule:根据响应时间分配一个weight,响应时间越长,weight越小,被选 中的可能性越低。 RetryRule:对选定的负载均衡策略机上重试机制。 RoundRobinRule:roundRobin方式轮询选择server RandomRule:随机选择一个server ZoneAvoidanceRule:复合判断server所在区域的性能和server的可用性选择server
09.openFeign的工作原理简要的概述一下?
(1)首先通过@EnableFeignCleints注解开启FeignCleint (2)根据OpenFeign的规则编写接口,并加@FeignCleint注解 (3)程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的接口,通过jdk的动态代理生成接口的实现类 (4)当实现类被生成的时候会根据反射的原理拿到@FeignClein的服务名执行服务发现的过程。 (5)得到某个服务名所有服务实例后执行负载均衡拿到一个实例 (6)通过反射读取到SpringMVC的注解,获取请求路径、参数等配置信息,执行服务服务调用 (7)序列化反序列化,发送请求,获得响应,返回
10.openfeign的重试机制如何配置?
feign重试机制实际使用用ribbon重试机制 由于ribbon有重试机制,所以正常情况下ribbon超时时间 < feign超时时间,如果ribbon重试期间,超过feign时间时,则会触发feign进行熔断。重试机制的配置方式: module-user-service: ribbon:
11.openfeign的超时机制如何配置?
使用Feign调用接口分两层,ribbon的调用和hystrix的调用,所以ribbon的超时时间和Hystrix的 超时时间的结合就是Feign的超时时间
module-user-service:
ribbon: ConnectTimeout: 500 #请求连接超时时间 ReadTimeout: 500 #请求处理的超时时间 MaxAutoRetriesNextServer: 2 #切换实例的重试次数 MaxAutoRetries: 1 #对当前实例的重试次数
hystrix: command: default: execution.isolation.thread.timeoutInMilliseconds: 3001 # 熔断超时时间 因为涉及到ribbon的重试机制,一般情况下 都是 ribbon 的总超时时间(<)hystrix的超时时间 超时时间计算公式:ReadTimeout*(MaxAutoRetries +1) * (MaxAutoRetriesNextServer + 1)
12.什么是服务降级?什么是服务熔断?它们是一个意思吗
首先这2个概念,不是一个意思。 **服务降级:**不管在什么情况下,服务降级的流程都是先调用正常的方法,再调用fallback的方法。 也就是服务器繁忙,请稍后再试,不让客户端等待并立刻返回一个友好提示。 **服务熔断:**假设服务宕机或者在单位时间内调用服务失败的次数过多,即服务降级的次数太多,那么则 服务熔断。 并且熔断以后会跳过正常的方法,会直接调用fallback方法,即所谓“服务熔断后不可用”。 类似于家里常见的保险丝,当达到最大服务访问后,会直接拒绝访问,拉闸限电,然后调用服务降级的fallback方法,返回友好提示 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态 (Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电 路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐 量, 并且断路器有自我检测并恢复的能力,其状态有3个状态: Closed:关闭状态(断路器关闭),所有请求都正常访问。 Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百 分比达到阈值,则触发熔断,断路器打开。默认失败比例的阈值是50%,请求次数最少 不低于20次。 Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5 秒 休眠计时。
13.简述下你对gateway网关它的理解
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用 其主要执行流程: 客户端向Spring Cloud Gateway发出请求。 如果Gateway Handler Mapping确定请求与路由匹配,则将其发送到Gateway Web Handler。 Handler通过指定的过滤器链将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器由虚线分隔的原因是,过滤器可以在发送代理请求之前或之后执行逻辑 **核心过滤器:GatewayFilter和GlobalFilter ** GatewayFilter : 通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上 GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器
14.如何定义一个GlobalFilter ?
定义一个全局过滤器需要继承 GlobalFilter 、 Ordered GlobalFilter : 需要重写 filter 方法,在其中实现自己的处理逻辑,很大部分都是对 exchange 进行操 作,取值赋值等等 Ordered : 需要重写 getOrder 方法,决定自定义 filter 在链中的位置,按照数字大小进行的排序
/
● 统计一次请求在filter链中的时长
●
● @author lw1243925457/
public class DurationStatisticsFilter implements GlobalFilter, Ordered {
private static final Log log =
LogFactory.getLog(DurationStatisticsFilter.class);
private static final String START_STAMP = "startStamp";
/*
● 请求响应时长统计
● 1.首先将请求进来时的时间戳写入到 exchange中
● 2.filter链走完后,无论成功或者失败,都视为完成,从exchange取出开始时间戳,打印时 长信息
● @param exchange the current server exchange
● @param chain provides a way to delegate to the next filter
● @return mono/
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
....
}
/*
- 这里简单位于 NettyWriteResponseFilter 之后吧
- @return order */ @Override public int getOrder() { return WRITE_RESPONSE_FILTER_ORDER - 1; } }
15.如何使用gateway进行限流?
常见的限流方式,比如Hystrix适用线程池隔离,超过线程池的负载,走熔断的逻辑。在一般应用服务器中,比如tomcat容器也是通过限制它的线程数来控制并发的;也有通过时间窗口的平均速度来控制流量。常见的限流纬度有比如通过Ip来限流、通过uri来限流、通过用户访问频次来限流。 一般限流都是在网关这一层做,比如Nginx、Openresty、kong、zuul、Spring Cloud Gateway等;也可以在应用层通过Aop这种方式去做限流。 我们做Java项目开发,如果是微服务一般可以把限流配置在微服务网关中(SpringCloud Gateway)。 限流方案:1)计数器算法 计数器算法采用计数器实现限流有点简单粗暴,一般我们会限制一秒钟的能够通过的请求数,比如限流qps为100,算法的实现思路就是从第一个请求进来开始计时,在接下去的1s内,每来一个请求,就把计数加1,如果累加的数字达到了100,那么后续的请求就会被全部拒绝。等到1s结束后,把计数恢复成0,重新开始计数。 2)漏桶算法 漏桶算法内部有一个容器,类似生活用到的漏斗,当请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变。不管服务调用方多么不稳定,通过漏桶算法进行限流,每10毫秒处理一次请求。因为处理的速度是固定的,请求进来的速度是未知的,可能突然进来很多请求,没来得及处理的请求就先放在桶里,既然是个桶,肯定是有容量上限,如果桶满了,那么新进来的请求就丢弃。漏桶算法存在一个缺陷,无法应对短时间的突发流量,比如双十一抢购、秒杀活动开始。 3)令牌桶算法 令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。
16.gateway的如何配置?
常需要配置的属性: 路由route: ⽹关最基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL、⼀系列的断⾔(匹配条件判断)和 Filter过滤器组 成。如果断⾔为true,则匹配该路由。 **断⾔predicates: ** 参考了Java8中的断⾔Predicate,匹配Http请求中的所有内容(类似于nginx中的 location匹配⼀ 样),如果断⾔与请求相匹配则路由。 过滤器filter: 标准的Spring webFilter,使⽤过滤器在请求之前或者之后执⾏业务逻辑。 请求前pre类型过滤器:做参数校验、权限校验、流量监控、⽇志输出、协议转换等, 请求前post类型的过滤器:做响应内容、响应头的修改、⽇志的输出、流量监控等。
rabbitmq
01.rabbitmq是什么
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等 方面表现不俗。具体特点包括: 1、可靠性(RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认) 2、灵活的路由(在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange ) 3、消息集群(多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker ) 4、高可用(队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。) 5、多种协议(RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。) 6、多语言客户端(RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。) 7、管理界面(RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。) 8、跟踪机制(如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了 什么。) 9、插件机制(RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件) AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向 消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限 制。
02.RabbitMQ 中的 Broker 是指什么?Cluster 又是指什么?
Broker ,是指一个或多个 erlang node 的逻辑分组,且 node 上运行着 RabbitMQ 应用程序。 Cluster ,是在 Broker 的基础之上,增加了 node 之间共享元数据的约束。
03.什么是元数据?元数据分为哪些类型?包括哪些内容?
在非 Cluster 模式下,元数据主要分为: Queue 元数据(queue 名字和属性等) Exchange 元数据(exchange 名字、类型和属性等) Binding 元数据(存放路由关系的查找表) Vhost 元数据(vhost 范围内针对前三者的名字空间约束和安全属性设置)
04.RabbitMQ 概念里的 channel、exchange 和 queue 是什么
queue 具有自己的 erlang 进程(队列); exchange 内部实现为保存 binding 关系的查找表(交换机); channel 是实际进行路由工作的实体,即负责按照 routing_key 将 message 投递给 queue(路由) 。 由 AMQP 协议描述可知,channel 是真实 TCP 连接之上的虚拟连接,所有 AMQP 命令都是通过channel 发送的,且每一个 channel 有唯一的 ID 。 一个 channel 只能被单独一个操作系统线程使用,故投递到特定 channel 上的 message 是有顺序的。但一个操作系统线程上允许使用多个 channel 。 channel 号为 0 的 channel 用于处理所有对于当前 connection 全局有效的帧,而 1-65535 号 channel 用于处理和特定 channel 相关的帧。
05.RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制
可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处理效率的下降
06.如何确保消息正确地发送至 RabbitMQ
RabbitMQ 使用发送方确认模式,确保消息正确地发送到 RabbitMQ。 发送方确认模式:将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被 指派一个唯一的 ID 。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道 会发送一个确认给生产者(包含消息唯一ID)。如果 RabbitMQ 发生内部错误从而导致消息丢失,会发 送一条 nack(not acknowledged,未确认)消息。 发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产 者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
07.什么情况下会出现 blackholed 问题
blackholed 问题是指,向 exchange 投递了 message ,而由于各种原因导致该 message 丢失, 但发送者却不知道。可导致 blackholed 的情况: 1、向未绑定 queue 的 exchange 发送 message 。 2、exchange 以 binding_key key_A 绑定了 queue queue_A,但向该 exchange 发送 message 使用的 routing_key 却是 key_B 。 如何防止出现blackholed问题? 没有特别好的办法,只能在具体实践中通过各种方式保证相关 fabric 的存在。另外,如果在执行 Basic.Publish 时设置 mandatory=true ,则在遇到可能出现 blackholed 情况时,服务器会通 过返回 Basic.Return 告之当前 message 无法被正确投递(内含原因 312 NO_ROUTE)。
08.消息怎么路由
从概念上来说,消息路由必须有三部分:交换器、路由、绑定。 消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。 通过队列路由键,可以把队列绑定到交换器上。 消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同 的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中;如果不能匹配到任何队列,消息将 进入 “黑洞”。 *常用的交换器主要分为一下三种: direct:如果路由键完全匹配,消息就被投递到相应的队列。 fanout:如果交换器收到消息,将会广播到所有绑定的队列上。 topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符, 比如:“” 匹配特定位置的任意文本, “.” 把路由键分为了几部分,“#” 匹配所有规则等。特别注 意:发往 topic 交换器的消息不能随意的设置选择键(routing_key),必须是由 "." 隔开的一系列的标识符组成
09.如何确保消息接收方消费了消息
RabbitMQ 使用接收方消息确认机制,确保消息接收方消费了消息 接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操 作)。只有消费者确认了消息,RabbitMQ 才能安全地把消息从队列中删除。 这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消息。也 就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。
10.如何避免消息重复投递或重复消费?
在消息生产时,MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id ,作为去重和幂等的依据 (消息投递失败并重传),避免重复的消息进入队列 在消息消费时,要求消息体中必须要有一个 bizId(对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等)作为去重和幂等的依据,避免同一条消息被重复消费。
11.RabbitMQ 有几种消费模式
RabbitMQ 有 pull 和 push 两种消费模式
12.RabbitMQ 允许发送的 message 最大可达多大
根据 AMQP 协议规定,消息体的大小由 64-bit 的值来指定
13.如何确保消息不丢失
消息持久化的前提是:将交换器/队列的 durable 属性设置为 true ,表示交换器/队列是持久交换器/队列,在服务器崩溃或重启之后不需要重新创建交换器/队列(交换器/队列会自动创建)。 如果消息想要从 RabbitMQ 崩溃中恢复,那么消息必须: 在消息发布前,通过把它的 “投递模式” 选项设置为2(持久)来把消息标记成持久化 将消息发送到持久交换器 消息到达持久队列 RabbitMQ 确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文 件。 当发布一条持久性消息到持久交换器上时,RabbitMQ 会在消息提交到日志文件后才发送响应(如果消 息路由到了非持久队列,它会自动从持久化日志中移除)。 一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ 会在持久化日志中把这条消息标记为等待 垃圾收集。如果持久化消息在被消费之前 RabbitMQ 重启,那么 RabbitMQ 会自动重建交换器和队列(以及绑定),并重播持久化日志文件中的消息到合适的队列或者交换器上。
14.RabbitMQ 中的 cluster、mirrored queue,以及 warrens 机制分别用于解决什么问题
cluster 是为了解决当 cluster 中的任意 node 失效后,producer 和 consumer 均可以通过其他 node 继续工作,即提高了可用性;另外可以通过增加 node 数量增加 cluster 的消息吞吐量的目的。 cluster 本身不负责 message 的可靠性问题(该问题由 producer 通过各种机制自行解决); cluster 无法解决跨数据中心的问题(即脑裂问题)。 另外,在cluster 前使用 HAProxy 可以解决 node 的选择问题,即业务无需知道 cluster 中多 个 node 的 ip 地址。可以利用 HAProxy 进行失效 node 的探测,可以作负载均衡 Mirrored queue 是为了解决使用 cluster 时所创建的 queue 的完整信息仅存在于单一 node 上的问题,从另一个角度增加可用性。 若想正确使用该功能,需要保证: 1)consumer 需要支持 Consumer Cancellation Notification 机制; 2)consumer 必须能够正确处理重复 message 。 Warrens 是为了解决 cluster 中 message 可能被 blackholed 的问题,即不能接受 producer 不停 republish message 但 RabbitMQ server 无回应的情况。
15.RabbitMQ 是否会弄丢数据
16.RabbitMQ 如何保证消息的顺序性
RabbitMQ保证消息的顺序性,就是一个 queue(队列)对应一个 consumer(消费者),然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
17.RabbitMQ 集群模式
Rabbitmq集群分为二种方式: 普通模式:创建好RabbitMQ集群之后的默认模式。 镜像模式:把需要的队列做成镜像队列。 普通集群模式:queue创建之后,如果没有其它policy,消息实体只存在于其中 一个节点,A、B两个Rabbitmq节点仅有相同的元数据,即队列结构,但K列的 数据仅保存有一份,即创建该队列的rabbitmq节点(A节点),当消息进入A节 点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行 消息传输,把A中的消息实体取出并经过B发送给consumer,所以consumer可 以连接每一个节点,从中取消息,该模式存在一个问题就是当A节点故障后,B 节点无法取到A节点中还未消费的消息实体。 镜像集群模式: 把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案(镜 像模式是在普通模式的基础上,增加一些镜像策略)该模式解决了普通模式中的数据丢失问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取,该模 式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在 对可靠性要求较高的场合中适用,一个队列想做成镜像队列,需要先设置policy。 客户端创建队列的时候,rabbitmq集群根据“队列名称”自动设置是普通集群模式或镜像队列的集群中有两种节点类型: 内存节点:只将数据保存到内存 磁盘节点:保存数据到内存和磁盘。 内存节点虽然不写入磁盘,但是它执行比磁盘节点要好,集群中,只需要一个磁盘节点来保存数据就足够了如果集群中只有内存节点,那么不能全部停止它们,否则所有数据消息在服务器全部停机之后都会丢失。 在一个rabbitmq集群里,有3台或以上机器,其中1台使用磁盘模式,其它节点使用内存模式,内存节点无访问速度更快,由于磁盘IO相对较慢,因此可作为数据备份使用。
dubbo
dubbo 和feign的区别
- 协议
Dubbo:支持多种传输协议(Dubbo、Rmi、Http、Redis),默认使用 Dubbo 协议;基于 Netty,TCP 传输,单一、异步、长连接,适合数据量小、高并发和服务提供者远远少于消费者的场景。 Feign:基于 Http 协议,短连接,不适合高并发访问。 2. 负载均衡 Dubbo:
- 支持 4 种算法(随机、轮询、活跃度、Hash 一致性),而且算法里面引入权重的概念。
- 配置的形式不仅支持代码配置,还支持 Dubbo 控制台灵活动态配置。
- 负载均衡的算法可以精准到某个服务接口的某个方法。
Feign:
- 只支持 N 种策略:轮询、随机、ResponseTime 加权。
- 负载均衡算法是 Client 级别的。
- 容错策略
Dubbo:支持多种容错策略:failover、failfast、brodecast、forking 等,也引入了 retry 次数、timeout 等配置参数。 Feign:利用熔断机制来实现容错的,处理的方式不一样。
01.dubbo是什么
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。 它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦 合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消 费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容。 Dubbo使用的是缺省协议, 采用长连接和nio异步通信, 适合小数据量大并发的服务调用,以及服务消 费者机器数远大于服务提供者机器数的情况。反之, dubbo缺省协议不适合传送大数据量的服务,比如传 文件,传视频等,除非请求量很低。
02.Dubbo的调用流程
**节点角色说明 ** Provider: 暴露服务的服务提供方。 Consumer: 调用远程服务的服务消费方。 Registry: 服务注册与发现的注册中心。 Monitor: 统计服务的调用次调和调用时间的监控中心。 Container: 服务运行容器。 **调用关系说明 **
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消 费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败, 再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
03.dubbo如何与SpringBoot集成
官方提供提供了集成库 dubbo-spring-boot ,对应仓库为 https://github.com/apache/incubator-dubbo-spring-boot-project
04.dubbo框架的分层设计
一共分成 10 层,总体是分层 Business、RPC、Remoting 三大层 Business Service 业务层:业务代码的接口与实现。我们实际使用 Dubbo 的业务层级(接口层,给服务提供 者和消费者来实现的) RPC config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 Spring 解析配置生成配置类(配置层,主要是对 Dubbo 进行各种配置的。) proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 扩展接口 为 ProxyFactory 。 registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService 。 cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance 。 monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService 。 Remoting protocol 远程调用层:封将 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter 。 exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec 。 serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool 。
05.Dubbo 支持哪些通信协议?
Dubbo 目前支持如下 9 种通信协议
dubbo:// ,默认协议
rest:// ,贡献自 Dubbox ,目前最合适的 HTTP Restful API 协议
rmi
webservice
hessian
thrift
memcached
redis
http
06.Dubbo 使用什么通信框架
Dubbo 在通信层拆分成了 API 层、实现层。项目结构如下:
API 层:
dubbo-remoting-api
实现层:
dubbo-remoting-netty3
dubbo-remoting-netty4
dubbo-remoting-mina
dubbo-remoting-grizzly
再配合上 Dubbo SPI 的机制,使用者可以自定义使用哪一种具体的实现
在 Dubbo 的最新版本,默认使用 Netty4 的版本
07.Dubbo 支持哪些序列化方式
Dubbo 目前支付如下 7 种序列化方式 Hessian2 :基于 Hessian 实现的序列化拓展。dubbo:// 协议的默认序列化方案。 Dubbo :Dubbo 自己实现的序列化拓展。 Kryo :基于 Kryo 实现的序列化拓展 FST :基于 FST 实现的序列化拓展。 JSON :基于 Fastjson 实现的序列化拓展。 NativeJava :基于 Java 原生的序列化拓展。 CompactedJava :在 NativeJava 的基础上,实现了对 ClassDescriptor 的处理。
08.Dubbo 有哪些负载均衡策略
Dubbo 内置 4 种负载均衡策略,默认使用 random 随机调用策略 Random LoadBalance(随机,按权重设置随机概率。) RoundRobin LoadBalance(轮询,按公约后的权重设置轮询比率。) LeastActive LoadBalance(最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。) ConsistentHash LoadBalance(一致性 Hash,相同参数的请求总是发到同一提供者)
09.Dubbo 支持哪些注册中心
Zookeeper【默认】 Redis Multicast 注册中心 Simple 注册中心 目前 Alibaba 正在开源注册中心 Nacos ,也是选择之一
zookeeper
01.zookeeper是什么
ZooKeeper 是一个开放源码的分布式协调服务,它是集群的管理者,监视着集群中各个节点的状态根据 节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用 户。 分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通 知、集群管理、Master 选举、分布式锁和分布式队列等功能。 Zookeeper 具有如下特性 1、顺序一致性(有序性) 2、原子性 3、单一视图 4、可靠性 5、实时性
02.Zookeeper 有哪些应用场景
Zookeeper 的功能很强大,应用场景很多,结合我们实际工作中使用 Dubbo 框架的情况, Zookeeper 主要是做注册中心用 当然,Zookeeper 能提供的不仅仅如此,再例如 1、统一命名服务。 2、分布式锁服务 3、配置管理。 4、注册与发现。 5、Master 选举。 6、分布式锁。 7、队列管理
03.Zookeeper 有哪几种节点类型
1、persistent持久节点:创建之后一直存在,除非有删除操作,创建节点的客户端会话失效也不影响 此节点。 2、persistent_sequential持久顺序节点:跟持久一样,就是父节点在创建下一级子节点的时候, 记录每个子节点创建的先后顺序,会给每个子节点名加上一个数字后缀。 3、ephemeral 临时节点:创建客户端会话失效(注意是会话失效,不是连接断了),节点也就没了。不 能建子节点。 4、ephemeral_sequential 临时顺序节点:基本特性同临时节点,增加了顺序属性,节点名后边会追 加一个由父节点维护的自增整型数字。
04.Zookeeper 的选举过程
Zookeeper 的选举算法有两种:一种是基于 basic paxos 实现的,另外一种是基于 fast paxos 算法实现的。系统默认的选举算法为 fast paxos Zookeeper 选主流程(basic paxos)
1、选举线程由当前 Server 发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的 Server 。
2、选举线程首先向所有 Server 发起一次询问(包括自己)。
3、选举线程收到回复后,验证是否是自己发起的询问(验证 zxid 是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的 Leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中。
4、收到所有 Server 回复以后,就计算出 zxid 最大的那个 Server ,并将这个 Server 相关信息设置成下一次要投票的 Server 。
5、线程将当前 zxid 最大的 Server 设置为当前 Server 要推荐的 Leader ,如果此时获胜的Server 获得 n/2+1 的 Server 票数,设置当前推荐的 Leader 为获胜的 Server ,将根据获胜的 Server 相关信息设置自己的状态,否则,继续这个过程,直到 Leader 被选举出来。
通过流程分析我们可以得出:要使 Leader 获得多数 Server 的支持,则 Server 总数必须是奇数 2n+1 ,且存活的 Server 的数目不得少于n+1 。每个 Server 启动后都会重复以上流程。
Zookeeper 选主流程(fast paxos) 由于 LeaderElection 收敛速度较慢,所以 Zookeeper 引入了 FastLeaderElection 选举算 法,FastLeaderElection 也成了Zookeeper默认的Leader选举算法。 FastLeaderElection 是标准的 Fast Paxos 的实现。它首先向所有 Server 提议自己要成为 Leader ,当其它 Server 收到提议以后,解决 epoch 和 zxid 的冲突,并接受对方的提议,然后 向对方发送接受提议完成的消息。重复这个流程,最后一定能选举出Leader。 FastLeaderElection 算法通过异步的通信方式来收集其它节点的选票,同时在分析选票时又根据投 票者的当前状态来作不同的处理,以加快 Leader 的选举进程。
05.为什么 Zookeeper 集群推荐节点数是单数
在统计投票时,有个过半的概念,大于集群机器数量的一半,即大于或等于(n/2+1) 半数以上投票通过才能决定Leader。所以,Zookeeper 集群推荐节点数是单数
Fegin
1. 什么是Feign
Feign是一个声明式的Web服务客户端,使得编写Web服务客户端变得非常容易, 只需要创建一个接口,然后在上面添加注解即可。
2. Fegin的底层原理实现
1.通过@FeginClient远程调用接口 2.通Jdk Proxy动态代理实例实现远程接口的调用,通过中央处理器(InvocationHandler 根据远程API的Method方法实例,进行MethodHandler方法处理分发)调用处理器分发远程调用 3.InvocationHandler 根据远程API的Method方法实例,进行MethodHandler方法处理分发 4.MethodHandler调用RequestTemplate根据实参构造Request实例 5.处理请求编码格式 6.对请求的拦截和日志处理 7.根据Http.client发送Http请求调用远程服务 8.根据Http Response进行响应编码处理以及响应后的拦截和日志处理 9.通过方法处理器调用中央处理器生成最终的响应结果