A.架构演变演变过程
传统架构 → 分布式架构 → SOA架构 → 微服务架构
B.分布式架构:
分布式架构就是将传统结构按照模块进行拆分,不同的人负责不同的模块,不会产生代码冲突问题,方便开发。
C.SOA架构:
SOA架构就是将业务逻辑层提取出来,将相似的业务逻辑形成一个服务,提供外部访问接口,服务之间访问通过RPC调用实现。
D.微服务架构架构:
微服务类似于SOA架构,但是比SOA架构粒度更细,更轻量。
E.微服务架构与SOA架构区别
SOA基于WebService和ESP实现,底层基于HTTP协议和使用XML方式传输,XML在网络传输过程中会产生大量冗余。微服务由SOA架构演变而来,继承了SOA架构的优点,同时对SOA架构缺点进行改善,数据传输采用JSON格式,相比于XML更轻量和快捷,粒度更细,更加便于敏捷开发。SOA数据库会存在共享,微服务提倡每个服务连接独立的数据库。
F. 微服务框架SpringCloud
什么是SpringCloud
SpringCloud是微服务的一种解决方案,依赖SpringBoot实现。包含注册中心(eureka)、客户端负载均衡(Ribbon)、网关(zull)、分布式锁、分布式会话等。(组件:服务协调,注册中心,熔断,降级,配置中心,网关)
为什么要使用SpringCloud
SpringCloud是一套非常完整的微服务解决方案,俗称“微服务全家桶”,几乎内置了微服务所使用的各种技术,可以不必集成第三方依赖。
Q:RPC和Restful分别有哪些优劣性?
RPC协议性能要高的多,吞吐量比http大。响应也更快。
RPC常见的序列化协议包括json、xml、hession、protobuf、thrift、text、bytes等;Restful使用http协议。http相对更规范,更标准,更通用,无论哪种语言都支持http协议
Q:为什么Rpc的性能比RestFul好一些?
RESTful是基于HTTP协议进行交互的,HTTP协议包含大量的请求头、响应头信息。而Rpc(比如dubbo)是基于(dubbo)自定义的二进制协议进行传输,消息体比较简单,传输数据要小很多。
Q:如果想实现一个Rpc框架,需要考虑哪些东西?
动态代理、反射、序列化、反序列化、网络通信(netty)、编解码、服务发现和注册、心跳与链路检测。
Q:服务端如何确定客户端要调用的函数?
在远程调用中,客户端和服务端分别维护一个【ID->函数】的对应表, ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,附上这个ID,服务端通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。(如果自己去设计一个RPC,可以使用一个Map去保存这些键值对)
Q:Dubbo:
服务提供者提供服务,服务消费者可以通过Rpc进行服务消费。
Q:Dubbo支持哪些协议?
Dubbo支持Dubbo、rmi、hessian、http、webservice、thrift、Redis等多种协议。
默认协议:Dubbo协议。
Dubbo:单一长连接和NIO异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者。传输协议TCP,异步 Hessian序列化。Dubbo推荐使用Dubbo协议。
RMI: 采用JDK标准的RMI协议实现,传输参数和返回参数对象需要实现 Serializable 接口,使用 Java 标准序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议TCP。 多个短连接 TCP协议传输,同步传输,适用常规的远程服务调用和RMI互操作。在依赖低版本的Common-Collections 包,Java 序列化存在安全漏洞。
WebService:基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多个短连接,基于 HTTP 传输,同步传输,适用系统集成和跨语言调用。
HTTP: 基于 Http 表单提交的远程调用协议,使用Spring的HttpInvoke 实现。多个短连接,传输协议HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用。
Hessian:集成 Hessian 服务,基于 HTTP 通讯,采用 Servlet暴露服务,Dubbo 内嵌 Jetty 作为服务器时默认实现,提供与 Hession 服务互操作。多个短连接,同步 HTTP 传输,Hessian 序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件。
Memcache:基于Memcache实现的RPC协议。
Redis:基于Redis实现的RPC协议。
Q:Dubbo的序列化有哪些方式?
hession、Duddo、Json、java序列化
Q:Dubbo协议有什么特点?
连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO 异步传输
序列化:Hessian 二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,
尽量不要用 dubbo 协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
Q:Dubbo和SpringCloud有哪些区别?
Dubbo是Soa(面向服务的架构),SpringCloud是微服务架构,除了服务,还有注册中心、熔断、配置中心。Dubbo基于Rpc(远程过程调用),SpringCloud基于restFul,基于http协议。
Q:Dubbo的服务提供者、服务消费者需要配置哪些信息?
服务提供者需要配置ip、端口、Dubbo协议、注册中心地址等
Q:Dubbo有哪些负载均衡策略?
一致性Hash均衡算法、随机调用法、轮询法、最少活动调用法。
Q:讲一下Dubbo的SPI机制。
SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展
Eureka 注册中心/服务治理
Q:讲一下Eureka.
例如:user-service对外提供服务,需要对外暴露自己的地址。而consumer(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与DevOps的思想是背道而驰的。
打个比方:这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。
此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。
此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前。
Eureka做什么?
Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。
同时,服务提供方与Eureka之间通过
“心跳”
机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。这就实现了服务的自动注册、发现、状态监控。
Eureka分为服务注册中心,服务提供者 ,服务消费者。服务提供者 、服务消费者都必须指定注册中心。服务提供者提供服务,而服务消费者可以调用提供者的服务。
Q:Eureka是怎么和服务通信的?
心跳机制。
Q:Eureka有哪些特性?
服务提供者有以下特性:服务续约:在注册完服务之后,服务提供者会维护一个心跳机制用来持续告诉Eureka Server: "我还活着 ” 。
EurekaServer有以下特性:
失效剔除:默认每隔一段时间(默认为60秒) 将当前清单中超时(默认为90秒)没有续约的服务剔除出去。自我保护:EurekaServer 在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%(通常由于网络不稳定导致)。 Eureka Server会将当前的实例注册信息保护起来, 让这些实例不会过期,尽可能保护这些注册信息。
Q:Eureka怎么保证高可用?
多个注册中心互相注册。Eureka Server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。
Q:Eureka注册中心和Zookeeper注册中心,有什么区别?
Eureka注重高可用,属于CAP中的AP。
Zookeeper注重一致性,属于CAP中的CP。
Q:除了Zookeeper,你用过哪些注册中心?有什么区别?
Zookeeper,Redis,Eureka
Zookeeper,是分布式中的CP,能够更好地保证分布式一致性。
Redis基于发布/订阅模式。
Eureka在SpringCloud中应用较多。Eureka是分布式中的AP,也就是注重可用性。服务消费 Feign
Q:讲一下Feign。
Q:为什么要使用Feign?
Feign可以进行服务消费,Feign内置了Hystrix和Eureka。
1.feign采用的是基于接口的注解。
2.feign整合了ribbon,具有负载均衡的能力。
3.整合了Hystrix,具有熔断的能力。
Q:Feign使用了哪些协议?
Http协议。
Q:Feign底层原理。
动态代理。
服务消费 Ribbon
Q:SpringCloud如何进行负载均衡?
使用Ribbon.
Q:Ribbon有哪些功能?
负载均衡,重试机制。
Q:Ribbon有哪些负载均衡的策略?
常用的有:轮询,随机,加权。随机策略:随机选择server.
轮询策略:按照顺序选择server(ribbon默认策略).
重试策略:在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server.
最低并发策略:逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server.
可用过滤策略:过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server(active connections超过配置的阈值).
响应时间加权重策略:根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间.
区域权重策略: 综合判断server所在区域的性能,和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server.
Hystrix熔断
Q:讲一下Hystrix。为什么要使用熔断?
当某个服务发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。
使用熔断,可以避免服务雪崩。
Q:Hystrix熔断的原理是什么?
"舱壁模式",实现进程线程池的隔离,它会为每一个服务创建一个独立的线程池,这样就算某个服务出现延迟过高的情况,也不会拖慢其他的服务。
Q:Hystrix熔断有哪几种方隔离方式?
线程池隔离。信号量隔离。
Q:这两种隔离模式,有什么区别?
在大部分情况下,使用线程池隔离会有非常微小的延迟(9ms),可以忽略不计。
如果对延迟的要求非常高的话,可以使用信号量隔离。
信号量的开销远比线程池的开销小,但是信号量不能设置超时,也没法实现异步访问。
Q:什么时候会触发熔断?什么时候断路器的状态会发生变化?
当QPS达到20,或者请求失败率达到50%,断路器就会变成打开,就会触发熔断。
断路器变成打开状态后,会进行休眠,默认5秒,在到达休眠时间后,将再次允许请求尝试访问,此时为"半开状态",若此时请求继续失败,那断路器又会进入"打开状态",如此循环。
Q:熔断如何设置超时时间,重试次数?
如果超时时间设置过短,或者重试次数过多,会频繁地重试,加大服务的压力。
如果超时时间设置过长,可能会导致请求响应慢,导致阻塞、卡顿。超时时间设置:方案一,按照服务提供者线上真实的服务水平,取 P999 或者 P9999 的值,也就是以 99.9% 或者 99.99% 的调用都在多少毫秒内返回为准。
方案二,按照接口重要性来进行设置,并发低的接口设置的超时时间可以多点,比如2s,并发高的接口设置的超时时间可以设置的低点,比如200ms。重试时间设置:一两次即可。大部分情况下,调用失败都是因为偶发的网络问题或者个别服务提供者节点有问题导致的,如果能换个节点再次访问说不定就能成功。
如果是读比较多的服务,重试次数设置多一些也没关系。如果是写比较多的服务,最好还是减少重试次数,或者不设置重试,否则容易出错。
Q:讲一下熔断和降级的区别?
熔断是直接返回一个错误响应。
服务降级是采取备用逻辑。
服务降级:当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
在服务降级逻辑中,我们需要实现一个通用的响应结果,并且该降级逻辑应该是从缓存或者是一些降级逻辑中获取,而不是依赖网络请求获取,这样能够稳定地返回结果的处理逻辑。
Q:Hystrix什么时候会触发服务降级?
当前Hystrix命令处于"熔断/短路"状态,断路器是打开的时候。
当前Hystrix命令的线程池,请求队列,或者信号量被占满的时候。Zuul网关
Q:Zuul网关,有什么功能?
Zuul能够进行过滤(Filter),设置白名单。
Zuul还能进行请求路由/服务路由。
路由功能,负责将外部请求功能转发到具体的微服务实例上,是实现外部访问统一入口的基础。
Q:Zuul网关如何实现路由?
通过服务路由的功能,在对外提供服务的时候,只需要通过暴露Zuul中配置的调用地址就可以让调用方统一的来访问我们的服务,而不需要了解具体提供服务的主机信息了。
Q:Zuul有几种过滤器类型?
4种。
pre : 可以在请求被路由之前调用。
适用于身份认证的场景,认证通过后再继续执行下面的流程。route : 在路由请求时被调用。
适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。post :在 route 和 error 过滤器之后被调用。
这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。error : 处理请求时发生错误时被调用。
在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。
Q:Gateway和Zuul有什么区别和联系?
Zuul:
使用的是阻塞式的 API,不支持长连接,比如 websockets。
底层是servlet,Zuul处理的是http请求
没有提供异步支持,流控等均由hystrix支持。
依赖包spring-cloud-starter-netflix-zuul。Gateway:
底层依然是servlet,但使用了webflux,多嵌套了一层框架。
依赖spring-boot-starter-webflux和/ spring-cloud-starter-gateway。
提供了异步支持,提供了抽象负载均衡,提供了抽象流控,并默认实现了RedisRateLimiter。
相同点:
1、底层都是servlet
2、两者均是web网关,处理的是http请求不同点:
1、内部实现:
gateway对比zuul多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等,扩展性也更强,但同时也限制了仅适合于Spring Cloud套件
zuul则可以扩展至其他微服务框架中,其内部没有实现限流、负载均衡等。
2、是否支持异步:
zuul仅支持同步。
gateway支持异步。理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定。
3、框架设计的角度:
gateway具有更好的扩展性,并且其已经发布了2.0.0的RELESE版本,稳定性也是非常好的。
4、性能:
WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好。使用非阻塞API。 Websockets得到支持,并且由于它与Spring紧密集成,所以将会是一个更好的开发体验。
SpringCould Config配置中心
Q:讲一下Config。
配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。
"一次配置,随处可用"。
- 1、Redis是基于C语言开发的高性能的缓存NoSQL数据库,
- 2、支持多种数据的类型
- a)字符串 key val
- b)hash key name filed
- c)list key v1 v2 v3 v3
- d)set key v1 v2 v3
- d)zset key s v
- 3、支持事务的提交
- 4、读写速度很快非常快
- a)首先是基于内存的
- b)Redis在处理读写命令的时候是单线程
- 1、优点
- a)数据类型丰富
- b)支持数据的提交
- c)支持主从复制
- d)支持读写分离
- e)支持事务提交
- 2、缺点
- a)Redis宕机后没有容错机制
1、高性能,高并发,减少和数据库的交互
- 1、分布式锁
- 2、缓存服务器
- 3、计数器
- 4、发布和订阅(MQ)
- 1、RDB:快照
- a)保存一瞬间的内存结构,持久化到磁盘
- b)内存结构是二进制文件
- c)恢复数据的时候非常的快
- d)默认机制是按照时间的进行快照
- 2、AOF:只读文件
- a)只保留写命令到磁盘中
- b)以文本的形式保持的磁盘中
- c)回复数据很慢(大文件)
- d)默认的持久化机制是每1s保存一次
- a)每次执行完写操作后马上保存本地
- 3、持久化的命令
- a)save:前台快照
- b)bgsave:后台快照
- 1、超时机制:每个key上面都要一个过期时间,时间到了后立马销毁。
- 2、惰性删除:用户在查询的时候先判断key是否超时,如果超时就销毁。
- 3、key超时后会被立马删除?
- a)不会
1、设置对应淘汰策略
- 0、Redis在内存不足的时候,会进行key的淘汰
- 1、LRU:最近很少使用原则
- a)从全部的key中选择
- b)从设置了过期时间的key中选择
- 2、LFU:最近一段时间使用的频率原则
- a)从全部的key中选择
- b)从设置了过期时间的key中选择
- 3、TTL:淘汰掉超时时间最短的key
- a)从全部的key中选择
- b)从设置了过期时间的key中选择
- 4、RANDOM:随机
- a)从全部的key中选择
- b)从设置了过期时间的key中选择
- 5、默认值:Redis内存满了后,只支持读,不支持写,写的时候回报错
- 6、抽取的样本
内存
- 1、写的时候报错
- 2、要么开始的key的讨论
- 1、给每个key都设置超时时间
- 2、根据业务场景选择了一个淘汰策略
- 3、要正确使用redis的数据结构
- 1、命令
- a)mulit:开启事务
- b)exec:提交事务
- d)discard:把队列中的命令丢弃(回滚的目的)
- 2、redis事务的细节
- a)redis开启事务后,把所有的命令都放入到一个队列中
- b)执行exec命令后,把队列中的命令重新的执行一遍
- c)队列中的命令只要有一个执行失败,这个队列中的内容所有命令都会被撤回
- 1、开启事务
- 2、添加命令到队列
- 3、exec/dicartd
- 1、单台Redis会存在读和写的瓶颈,而且还会存在单点故障。
- 2、Redis集群的模式
- a)主从架构模式:把多态Redis节点分为,一主多从,主负责写的操作,从负责读的操作
- 1)数据的备份
- 2)提供Redis的读的速度
- b)读写分离:主数据只负责写的操作,从数据库只负责的读的操作
- c)哨兵机制:对Redis节点的监控和选举
- a)哨兵的数量至少是3台
- 3、redis主从选举
- a)从哨兵中选举leader
- 1)单台哨兵认为主节点宕机了是主观下线
- 2)一半以上哨兵认为主节点宕机后是客观下线
- a)哨兵之间投票(认为主观下线的哨兵会发请求给其他的哨兵,把票投给发消息的哨兵,如果此时该哨兵已经投票给其他的哨兵次票数作废)
- b)票数过半的哨兵成为哨兵中的leader
- b)从节点中选举leader
- 1)此时的leader由哨兵的leader来决定
- 2)选举优先级(slave-priority)最大的从节点作为主节点,如不存在则继续
- 3)选举偏移量(决定了数据的最新程度)最大的从节点作为主节点,不过不存在则继续
- 4)选择runid(redis每次启动的时候生成随机的runid作为redis的标识)最小的从节点作为主节点
- 1、全量复制:发送节点初始化
- 1)负责和主节点建立连接
- 2)做验证
- 3)从发送一个同步命令给主
- 4)主收到同步的命名启动一线线程做后台快照,把新的命令放到缓存区中
- 5)快照结束后把二进制文件发送从从
- 6)从接收到这个文件后,丢弃自己的所有数据,然后把二进制加载到自己的节点中
- 7)主再把缓存区中的命令发送给从
- 8)从接收缓存区中的命令,执行
- 2、增量复制:发送节点初始化完成后
- a)主节点收到写的命令后现在自己的节点中执行
- b)在把这个命令发送所有的从
- 1、Redis集群中会自动分配hash槽,所有的数据都是放到对应的擦槽中。
- 2、Redis集群中总共有16384个hahs槽
- 3、在执行的写命令的时候,首先会把key按照一种算法得到一个结果,把这个结果除以16384取余得到hash槽的位置,就会把这个key放入到指定的hash槽。
- 4、Redis集群中有一致性的概念吗???无中心
- 5、可以在Redis集群中可以给每个节点单独搭建主从
16384
setnx
- 1、出现的原因
- a)数据库中没有,缓存中也没有
- b)查询商品id为-1
- 2、如何解决
- a)设置默认值(如果从数据库中没有查到,就给缓存中放一个默认值)
- b)对数据的进行过滤,过滤掉id为负数的
- 1、出现的原因
- a)数据库中有,但是缓存中没有
- b)并发访问一条数据
- 2、如何解决
- a)设置布隆过滤器
- a)在布隆过滤器中可以判断一个商品一定不存在或者有可能存在。
- b)设置热点数据不过期
- c)设置分布式锁
- 1、出现的原因
- a)批量的key同时过期
- b)并发访问这些key
- 2、如何解决
- a)设置key过期的时间是随机的
- b)设置热点数据不过期
- 1、出现的原因
- a)发生在项目上线的时候,热数据需要提前放入到缓存中
- 2、如何解决
- a)数据量不大上线后可以人工把数据导入到缓存中
- b)定时热刷新
更新数据库的时候刷新缓存(清空)
- 1、为什么要使用MQ?
- a)模块和模块之间的耦合
- b)模块和模块调用使用同步的
- 2、MQ的优点
- a)解耦
- b)异步
- c)限流
- 1、no-ack:队列把消息给消费者后就认为消费者已经把这个消息给消费了。
- 2、手动ack:队列把消费给消费者后,该条消息的状态变为待应答,需要消费者手动确认后消息才能从队列中删除
- a)消费者消费完任务后,在发送手动ack时候出现了异常,队列会把这个消息发送一个另一个消费者,另消费者将接着消费,又出现了重复消费的问题
- b)记录每条消息的一个消费的状态
- 1、RabbitMQServer
- 2、Vhost
- 3、Channle
- 4、Exchange
- a)hello-word-->一个提供者,一个队列,一个消费者
- b)work--->一个提供者,一个队列,两个消费者
- a)队列给轮训把消息发送给每一个队列
- b)可以设置不同的消费者,消费不同的数量
- c)faout(广播)-->一个提供者,一个交换机,多个队列,多个消费者
- d)完全路由:一个提供者,一个交换机,路由键(INFO,ERROR),多个队列,多个消费者
- e)表达式路由:一个提供者,一个交换机,路由键(),多个队列,多个消费者
- a)#:可以匹配到多个
- b)*:只能匹配到一个
- 5、Routing
- 6、Queue
- 7、Provider
- 8、Consumer
- 9、Binding
- 1、MQ模型
- a)hello-word-->一个提供者,一个队列,一个消费者
- b)work--->一个提供者,一个队列,两个消费者
- a)队列给轮训把消息发送给每一个队列
- b)可以设置不同的消费者,消费不同的数量
- c)faout(广播)-->一个提供者,一个交换机,多个队列,多个消费者
- d)完全路由:一个提供者,一个交换机,路由键(INFO,ERROR),多个队列,多个消费者
- e)表达式路由:一个提供者,一个交换机,路由键(),多个队列,多个消费者
- a)#:可以匹配到多个
- b)*:只能匹配到一个
- 2、消息发送的流程
- a)提供者(交换机,路由键,消息)---》交换机(路由键)--》队列--》消费者
1、根据提供者的路由键和交换机绑定的路由键进行匹配
1、根据提供者的路由键和交换机绑定的路由键进行匹配
- 1、如何确保消息正确地发送至 RabbitMQ
- a)开启confirm确认机制,当消息到交换机后会异步的通知
- b)reuting:从交换机发送到了队列中
- 2、如何确保消息接收方消费了消息
- a)手动ack
- 1、如何确保消息正确地发送至 RabbitMQ
- a)开启confirm确认机制,当消息到交换机后会异步的通知
- b)reuting:从交换机发送到了队列中
- 2、如何确保消息接收方消费了消息
- a)手动ack
- 3、队列持久化
- 1、分布式服务治理框架
- 2、两个核心
- a)文件系统
- b)监听通知机制
- 3、解决的问题
- a)服务的注册和发现
- b)分布式锁
- c)订阅和发布
- d)服务命名
- 1、ZK集群中有三个角色
- a)leader(领导):负责写的数控
- b)follower(追随者):负责读,参与的选举
- c)observer(观察者):不参与选举
- 2、数据的同步的问题
- a)写命令leader来做,leader在广播给所有的follower,所有的follower返回写入的一个状态,如果有一半以上成功leader就广播发送提交事务的命令
- 1、永久有序
- 2、永久无序
- 3、临时有序
- 4、临时无序
- 1、客户端对zk的某个节点进行监听
- 2、其他客户端客户端对zk的的某个节点进行修改
- 3、zkServer感知到某个节点下数据的变化
- 4、zkServer会调用监听了这个节点的客户端(回调)
- 5、把修改的内容通过事件的方式传递到监听器
- 1、注册域发现
- 2、分布式锁
- 3、命名服务
- 4、选举
- 5、配置文件管理
- 1、查询子节点 ls /demo
- 2、添加 create -s/e /demo/znode
- 3、查询节点的内容 get /demo
- 4、del/rmi /demo
- 1、在zk集群名中至少需要3台
- 2、2n+1(奇数台和耦合台容灾能力是一样的)
- 3、过半数存活原则:整个集群中的节点必须有一半以上存活这个集群才能正常提供服务。
- 4、为什么会出现这个原则
- a)zk在CAP原则中选择的强一致性
- b)为了防止脑裂的问题
- 1、节点宕机
- a)跟随者:这个节点宕机后,影响并不是很大
- b)领导者:这个节点宕机后就要从跟随者中选举出一台来做新领导者,zk在选举的过程中是需要一定的时间,在这段时间内zk是不提供服务的。
- 服务器具有四种状态,分别是LOOKING、FOLLOWING、LEADING、OBSERVING。
- LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
- FOLLOWING:跟随者状态。表明当前服务器角色是Follower。
- LEADING:领导者状态。表明当前服务器角色是Leader。
- OBSERVING:观察者状态。表明当前服务器角色是Observer。
- 1、Dubbo是远程调用框架(RPC),可以实现服务和服务之间的远程调用,但是都是点对点的。服务一旦很多就会造成很多的问题的。
- 2、使用zk作用注册中心,统一化管理的。调用服务首先去注册中心获取服务相关信息。
- 1、如果不是第一次调用,那么在调用方是存在缓存的,可以从本地村换获取服务地址信息调用
- 2、如果是第一次不能进行调用。
监控中心只是动态的读取zk中的数据,以图形化的界面显示出来。
- 利用节点的特性来储存消费者和生产者的信息
- a)dubbo
- a)接口全类名
- a)provider
- a)提供者的信息(dubbo://ip:20880?)
- b)conscumer
- b)消费这的消息(consumer:ip?xxx)
- c)routes
- d)config
- 1、轮训
- 2、随机
- 3、最小活跃数
- 4、hash
- 5、在注解中配置
- 1、注册中心更好
- a)解耦啊
- b)支持负载均衡
- 2、直连
- a)在注解上直接设置url属性
- b)提供者的端口号后者ip变了以后,消费者这边也需要做对应的改变。
- 1、Dubbo底层通讯的原理
- a)socket
- b)netty---》nio
- 2、Dubbo通讯协议
- a)走的Dubbo协议
- 3、为什么要使用netty
- a)netty底层基于NIO
- a)同步的非阻塞状态
- b)多路复用器
- b)netty中使用主从线程模型
Tomcat是一个apache下面的一个开源项目,轻量级,免费的Web服务器。
- 1、在tomcat的conf/server.xml中修改
- 2、接收HTTP请求:8080
- 3、接收HTTp请求,停止的8005
- 3、接收其他服务端转发过来的请求:8009
- 1、直接把war包部署到webapps下面
- 2、远程部署(通过manager项目)
- 3、在servet.xml中设置Context节点部署
- 1、首选tomcat启动
- 2、会加载webapps下面项目(标准的web项目)
- 3、加载项目中的web.xml文件
- 4、解析web.xml
- 5、通过反射实例化servlet(如果优先级设置为1)
- 1、BIO:同步阻塞,但线程模型
- 2、NIO:同步非阻塞,多路复用器
- 3、AIO:异步非阻塞
- 4、在server.xml中8080端口的protocol属性修改
- 1、单例模式:整个容器中只有一个实例
- a)饿汉式
- b)懒汉式
- c)servlet是单列的,Runtime
- 2、工厂设模式:把所有的bean创建都交给一个bean处理
- a)spring
- 3、代理设计模式:把系统服务和业务主体分离
- a)spring
- b)MybatisMapper
- 4、观察者设模式:主要对某个bean监控
- a)spring
- 5、装饰着设计模式
- 6、模板(XxxxTemplate)
- 7、适配器设计模式
- 8、责任链设计模式
- 9、门面设计模式
- 1、设计模式很很多开人员经过多年的试错和经验,总结的触一套解决方案,主要是解决代码的扩展性(延伸性),复用性。
- 2、设计模式23中,分为3中类型
- a)创建性
- b)行为性
- c)结构性
- 1、分布式
- a)主要解决了单体结构存在一个性能瓶颈,按照不同的业务拆分,不同的业务可以部署到不同的机器上面,服务和服务之间通过远程调用的方法通讯。
- b)分布式架构中需要考虑点
- 1)分布式锁
- 2)分布式事务
- 3)分布式任务
- 2、水平扩展:按照横向的方式添加机器来实现
- 3、垂直拆分:按照不同的业务进行拆分,部署到不同的机器上面
- 4、集群:不同机器中运行着相同的应用,可以通过负载均衡把请求平摊到每个机器上。
- 5、可扩展性:通过添机器的方式来解决项目的问题,需要考虑到项目是要识别到新加的机器,尽量不要重启。
- 6、高可用性:服务出现故障后,依然是可用的,可以通过服务的熔断,降级来实现,选举
- 7、负载均衡:主要就是反向代理,按照某种规则给服务器做代理,
- 8、集群容错:出现网络问题或者节点本身的故障,要有对应的解决方案。
- 9、多线程:项目中使用多线程就是提供CPU的使用率,处理任务的速度也就快了
- 10、高并发:在短时间内会有大量的请求过来。
- 1、一致性:节点和节点的数据必须要保持一致
- 2、可用性:节点出现故障的时候,服务需要正常提供访问,对数据的要求可以不是最新的。
- 3、分区容错性:在出现网络故障的时候仍然要保持节点节点正常的访问,一致性或者可用性中选择其一。
- 4、Eureka和ZK
- a)ZK:CP
- b)Eureka:AP
- 5、Dubbo和SpringClooud区别
- 1、BASE理论是基于CAP的思想衍生而来的,牺牲了强一致性获得可用性
- 2、强一致性和最终一致性区别
- a)强一致性:在任何时间点节点中的数据都要保持一致
- b)最终一致性:允许在在一段时间内不一致,但是保证最终的一致性。
- 2、核心思想:牺牲部分功能要保证核心功能可用,允许数据在一段时间内不一致,但是要保证最终一致。
- 3、状态
- a)可用性:牺牲部分功能要保证核心功能可用
- b)软状态:节点之间同步的数据的一个中间状态(支付中,同步中。。。)
- c)最终一致性:经过一段时间后最终数据要保持一致
- 1、Netty是基本事件驱动的高性能的通讯框架,底层封装了NIO,多路复用器来提供它的效率。
- 2、各种IO
- a、BIO:同步阻塞
- b、NIO:同步非阻塞
- c、AIO:异步非阻塞
- 3、Netty在对NIO封装的基础之上又做了优化
- a)线程模型
- 1)单线程模型
- 2)多线程模型
- 3)主从线程模型
- b)链式编程
- 1)in
- 2)out
- 1、高性能:NIO,多路复用器(事件)
- 2、封装好:对NIO做了封装,使用起来很简答
- 3、Netty社区活跃度比较高
- 1、Dubbo使用Netty实现了远程调用
- 2、Http服务器
- 3、FTP服务器
- 4、WebSocket服务器
- 5、RPC服务器
- 1、BIO:同步的阻塞
- 1)数据通过byte储存
- 2)操作的流
- 3)启动一个线程池处理,为每个Socket启动一个线程去处理
- 4)单向通道
- 2、NIO:同步的阻塞
- 1)数据是通过ByteBuffer
- 2)操作的channel
- 3)多路复用器,把所有的socket绑定到多路复用器上,设置触发的事件,然后多路复用器遍历得到事件的对象,然后在启动一个线程处理。
- 4)双向通道
- 1、ByteBuffer
- 1)postion:位置
- 2)limit:边界
- 3)capacity:容量
- 4)allocate(1024):创建一个指定的长度的ByteBuffer
- 5)flip();转为可读模式
- 2、Channel:通道
- 1)FileChannel
- 2)ServerSocketChannel
- 3)SocketChannel
- 3、Selector
- 1、单线程模型
- 2、多线程模型
- 3、主从线程模型
- 1、EventGroup:事件循环组
- 2、ServerBootStrap:启动服务端的引导类
- 3、BootStrap:启动的客户端的引导类
- 4、ChannelHanlder:处理出栈和入栈的数据
- 1)IN
- 2)OUt
- 5、ChannelPipeLine:链式的管理ChannelHanlder
- 6、ChannleFtrue:Netty的很多操作都是异步的,所以可以通过这个对象来判断异步的操作是否已经完成
- 1)阻塞
- 2)设置监听器,netty异步处理完成回调这个方法,在这个方法中做判断
- 1、cpu核数的2倍
- 2、调用bind方法后开始启动
- 1、ReadTimeoutHandler:读取超时时间(在指定的时间内,没有读取到客户端的消息,连接自动断开)
- 2、WriteTimeoutHandler:写的超时时间(在指定的时间内,没有写数据给客户端,连接自动断开)
- 3、需要设置的channle链中
- 1、一范式:表中的所有的字段都是不可再拆分的原子值--》原子性
- 2、二范式:表中的字段要和主键直接相关 --》一张表中只能保存一类数据
- 3、三范式:表中的字段要和注解直接相关,而不能间接相关--》表和表的关联关系
- 1、索引是特殊的文件,具体特殊的储存结构
- 2、索引是保留的数据修改的引用指针
- 3、添加索引可以提高查询的效率
- 4、可以理解为书的目录
- 1、经常被查询的字段
- 2、表和表之间的关联字段
- 3、主键或者排序字段
- 4、不要在索引列上做计算
- 5、不要再经常被修改的字段上添加索引
- 6、尽量的扩展索引,在一个是索引中包含多个字段
- 7、适当的建立前缀索引
- 8、大文本,二进制,状态值不、适合建立索引
- 1、不是
- 2、索引的效果是在大数量的量的情况下才能提前出来
- 3、添加适当的索引,运行的sql要使用到索引才能提高查询的效率
- 1、先删除索引
- 2、在删除数据
- 3、在重建索引
- 1、事务的四大特性
- 1、原子性:要么一起成功,要么一起失败
- 2、一致性:从一个状态到另一个状态需要保持一致。
- 3、隔离性:事务和事务的隔离级别
- 4、持久性:事务一旦提交永久保存
- 2、事务的隔离级别
- a)读未提交:
- b)读已提交(Oracle):
- c)可重复读(MySQL):
- d)序列化:
- 4、隔离级别不同会出现如下的情况
- 1)脏读:读取到了另外一个没有提交的事务
- 2)不可重复读:一个事务多次读取结果不一样
- 3)幻读:一个事务在修改,另一个事务在添加
- 1、varchar(100)
- a)长度:长度是可变的
- a)hello
- b)速度:慢一点
- 2、char(100)
- a)长度:长度是不可变的
- a)hello
- b)速度:速度更快
数据最大的长度
- 1、相同点
- a)可以将多个结果集合并
- 2、不同点
- a)UNION ALL:直接合并,不会考虑到去重
- b)union:先去重,然后再合并在一起。
- a)去重条件是对比每个结果集select后面的字段
- 1、添加索引
- 2、优化是sql
- 3、使用缓存(Redis+Ehcache)本地缓存加分布式缓存
- 4、引擎,分库分表
- 1、乐观锁:在修改的时候不会认为其他事务也在修改,可以直接修改
- a)使用版本号实现,在更新的时候 udpate 表明 set xxx=xxx,versiono = version + 1 where id = 1 and version = 1
- 2、悲观锁:在修改的时候就会认为,其他事务也会修改,所以会上锁
- a)数据库:select * from t_user where id >10 for udpate
- 1)事务提交后释放锁
- b)Java程序中如何实现
- 1)同步的关键字,同步代码块
- 2)线程的等待,唤醒
- 3、sleep和wait方法的区别
- a)sleep:指定睡眠的时间
- a)不会释放锁
- b)指定的时间后自动唤醒
- b)wait:调用后开始休眠
- a)会把锁释放
- b)需要notify()或者notifyall()换新
- 1、把一个查询的结果,作为另一个查询的条件
- 2、子查询性能很慢
- 3、子查询出现的地方很多
- 1)from后面
- 2)select (select name from xxx where id = u.id)
- 3)where后面
- 4)having后面