概述
Eureka服务注册和发现原理
- 有三个角色
服务提供者(Eureka client)
向服务注册中心注册自己的信息
服务消费者 (Eureka client)
向服务注册中心注册自己的信息,并获取自己要消费的服务提供者信息
注册中心 (Eureka Server)
接收服务消费者和提供者的注册的信息
dubbo + ZK如何实现CP、Eureka怎么实现AP
- dubbo + zk
当向注册中心查询服务注册列表时,可以容忍注册中心返回的是几分钟以前的注册信息,但是不能接受服务直接down掉不可用。服务注册功能对可用性的要求高于一致性。在zk选举的时候,整个集群不可用,这样就导致注册服务瘫痪,漫长的选举期间导致整个注册服务长期不可用
- Eureka 的AP
在设计的时候优先保证可用性。eureka的各个节点都是平等的,几个节点down掉不会影响其他节点的提供注册和查询服务的功能。而Eureka的客户端在向牧歌Eureka注册如果链接失败,则会自动切换到其他节点,只要有一台Eureka正常工作,就能保证注册服务可用,只不过查询服务的结果可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内,85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没有收到心跳的而过期的服务;
- Eureka仍然能够接收新的服务注册和查询请求,但不会同步到其他节点(保证当前节点依然可用);
- 当网络稳定时,当前实例新的注册信息会同步到其他节点;
因此,Eureka可以很好的应对网络故障导致部分节点失去联系的情况,而不会像zk那样因为选举导致整个集群不可用
总之,dubbo+zk强调的是CP,强一致性,是zk的特性决定,而Eureka强调的是AP,高可用
Hystrix怎么实现熔断机制
Hystrix包括
服务降级
,服务熔断
,线程合信号隔离
,请求缓存
,请求合并
,服务监控
- hystrix对于依赖服务采用依赖隔离的方式主要有线程隔离合信号量隔离
- 线程隔离:卫每个依赖服务创建一个独立的线程,性能上低于信号量隔离
- 信号量隔离:用信号量控制单个依赖服务,开销小于线程隔离,但无法异步和设置超时。
- 定义服务降级
fallback
是实现服务降级的后备方法。只要在fallbackmethod
属性指定的对应的方法就可。
- 异常处理
- 忽略异常:对某个异常,不调用fallback操作,而是抛出
@HystrixCommand(ignoreExceptions = {需要忽略的异常类.class})
- 异常分类降级:根据不同的异常,采用不同的降级处理
- 请求缓存
@CacheResult
:标记请求命令的结果应该被缓存,必须和@HystrixCommand
注解结合使用,所用属性有:cacheKeyMethod
/* 代码中CacheResult代表开启缓存功能,当调用结果返回后Hystrix缓存,缓存的key值不指定就使用该方法中的所有参数, */ @CacheResult(cacheKeyMethod = "getNameByidCacheKey") @HystrixCommand(fallbackMethod = "hiFallback") public String hiService(String name) { return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class); } private Long getNameByidCacheKey(Long id) { return id; }
- 删除缓存:标记请求命令的缓存失效,失效的缓存根据定义的Key决定,常用属性 :command、cacheKeyMethod
@CacheResult @HystrixCommand(fallbackMethod = "hiFallback") public String hiService(@CacheKey("name") String name) { return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class); } @CacheRemove(commandKey = "hiService") public void update(@CacheKey("name")User user){ restTemplate.getForObject("http://USER-SERVICE/users",user,User.class); }
redis数据类型,底层是什么。
String
redis集群原理,怎么实现高可用,一致性hash算法。
redis怎么实现主从同步的。
dubbo工作原理,生产者、服务者之间是怎么通信的
摘抄自官网
- 调用关系说明
- 0:服务容器负责启动,加载,运行服务提供者。
- 1.服务提供者在启动时,向注册中心注册自己提供的服务。
- 2.服务消费者在启动时,向注册中心订阅自己所需的服务。
- 3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
dubbo负载均衡
- 随机负载均衡(RandomLoadBalance):先统计所有服务器上该接口方法权重总和,然后再随机nextInt,看生成的随机数落在哪个段内,就调用哪个服务。默认使用的就是随机轮询算法
- 轮询(RoundRobinLoadBalance):如果所有服务器接口方法的权重都一样,依次调用;
最少活跃负载均衡(LeastActiveLoadBalance)
dubbo容错,服务治理
在dubboAdmin中,可以对具体的服务设置响应的权重、负载均衡等设置
hashmap为什么线程不安全
在进行扩容的时候,由于要将原有链表中的数据重新进行rehash运算,原有的链表顺序会由于rehash原因被定位到其他的数组下标下面,在并发多线程的情况下,存在同时其他元素的put操作,如果hash值相同,可能造成环形链表
服务隔离
垃圾回收算法有哪些,优点和不足
- 标记-清除(mark swap)
- 将标记成垃圾的对象清除出内存,容易造成内存空间的不连续性,在分配打对象的时候,由于连续空间的不足而频繁触发内存回收;
- 适用于老年代,对象存活时间长的内存区域
- 复制
- 将内存块等分成相同大小的内存块。一块用于对象存储。当垃圾回收的时候,将未被标记回收的内存复制到另一块 内存块,然后剩下的就全部是要回收的内存
- 缺点:只有一半的内存被使用
- 优点:未回收的内存块还是连续的
- 适用于新生代:朝生暮死的区域。在新生代中,又被分为Eden,survivor区,Eden区分配的对象都是朝生暮死;eden与survivor的比例时8:1;在Eden区,使用的回收算法是复制算法
- 标记-整理
- 标记-清除的升级版本。将不用回收的内存区域移到一起,然后再集中处理需要回收的区域
在dubbo中,如果zookeeper不工作的话,消费者能否调用到服务者
a. 能调用到,zookeeper不工作的时候,消费者能取得本地缓存的地址列表直接调用服务者
b. 消费者能绕过zk来直接发起调用,在使用url标签,直接指定哪个提供者
为什么要用分布式锁分布式锁有哪些,怎么实现
jvm内存模型,各个模型存储的是什么。
redis与memcache的相互比较
- redis和memcache都是将数据放置到内存中,memcache还能存放图片、视频等数据;
- redis除了K/V类型数据,还支持List,Set,Zset,List,Hash这些数据类型
- 在redis中,当内存存满数据后,它会将不常用的value写到磁盘中;
- 过期策略-memcache在set时就指定。redis可以只用expire来设定
- 集群-memcache利用magent做一主多从;redis可以做一主多从,一可以做一主多从;
- 安全性-memcache挂掉后,所有的数据就没了;redis可以定期持久化到磁盘中
- 容灾恢复-memcache挂掉后,数据不可恢复,redis可以通过aof恢复
- redis支持数据的备份,即master-slave模式数据备份
- redis与memcache的异同点
- 存储方式
- 数据类型
- 底层模型
运行环境
redis为什么这么快
- 单线程
IO非阻塞多路复用
I/O多路复用实际上是指多个连接的管理可以在同一进程。多路是指网络连接,复用只是同一个线程。在网络服务中,I/O多路复用起的作用是一次性把多个连接的事件通知业务代码处理,处理的方式由业务代码来决定。在I/O多路复用模型中,最重要的函数调用就是I/O 多路复用函数,该方法能同时监控多个文件描述符(fd)的读写情况,当其中的某些fd可读/写时,该方法就会返回可读/写的fd个数。
Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll的read、write、close等都转换成事件,不在网络I/O上浪费过多的时间。redis主从备份原理过程
slave发送sync指定,此时master执行bgsave命令进行全量备份,并缓存所有的写命令;等bgsave执行完后,将rbd发送给slave,然后slave将数据写入;写入完所有快照后,master再发送缓存的写指定到slave,slave就写相应的数据,之后的增量的同步的方式同步master数据
- 同步方式
bgsave - 全量备份
AOF(append only file)- 增量
redis cluster的高可用和主备切换原理
- 判断节点宕机
如果一个节点认为另外一个节点宕机,那么就是pfail
主观宕机。如果多个节点认为另外一个节点宕机,那么就是fail
,客观宕机,跟哨兵原理一致,sdown
,odown
。 从节点过滤
对宕机的master节点,从其所有的slave的节点中选择一个切换成 master节点。
检查每个slave节点与,master的断开实践,如果超过了 cluster-node-timeout * cluster-slave-validity-factor
该slave节点就没有资格晋升为master节点了。
从节点选举
每个从节点都根据自己对master复制数据的offset,来设置一个选举时间,offset越大(复制的数据越多)的从节点,选举时间越靠前,优先进行选举。
所有的master node开始slave选举投票,给要进行选举的slave进行投票,如果大部分master 节点(n/2 + 1)
都投票给了某个从节点,那么该从节点就晋升成master。redis节点间的内部通信机制
- 基本通信原理
集群元数据的维护有两种方式:集中式
,Gossip协议
。redis cluster节点间采用的是gossip协议。- 集中式是将集群元数据(节点信息,故障etc)集中存储在某个节点上。
- redis集群维护元数据采用
gossip
协议,所有节点都持有一份元数据,不同节点如果出现了元数据的变更,就不断将元数据发送给其他的节点,让其他节点也进行元数据变更。
集中式
与Gossip
协议的优缺点- 集中式的好处在于元数据的读取更新时效性非常好,一单出现数据变更,就立刻更新到集中式的存储中,其他节点读取的时候可以随时感知;不足之处是所有的元数据的更新集中于一个地方,可能会导致元数据的存储有压力。
Gossip
协议的好处在于元数据比较分散,不是集中在一个地方,更新请求会陆陆续续打到所有节点上去更新,降低压力;不足之处,元数据更新有延迟,可能导致集群中的一些操作会滞后;- 10000端口:每个节点都有一个鱼鱼节点间通信的端口。每个节点每隔一段时间会往其他节点发送
ping
消息,同时其他几个节点接收到ping
后返回pong
. - 交换信息:交换的信息包括故障信息、节点增加和删除,hash slot 等信息
- 10000端口:每个节点都有一个鱼鱼节点间通信的端口。每个节点每隔一段时间会往其他节点发送
- Gossip协议
gossip协议包括多种消息,包含ping
,pong
,fail
- meet: 某个节点发送meet给新加入的节点,让新节点加入集群,然后新节点会开始与其他节点进行通信。如下指令就是发送meet消息给新加入的节点,通知先加入的节点加入集群
redis-trib.rb add-node
- ping:每个节点会频繁的给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据。
- pong: 返回ping和meet,包含自己的状态和其他信息,也用于信息广播和更新。
fail:某个节点判断另外一个节点fail后,就发送fail给其他节点,通知其他节点说,某个节点宕机了。
redis cluster的hash slot算法
redis cluster有固定的16384个slot。对每个key进行
CCR16
值,再对16384取模。这样就能获取到可以对应的hash slot。
redis clsuter中队每个master都会持有部分的slot,如果有3个master,那么每个master就持有 16384 /3 个hashslot。hash slot 让节点的增加和移除很简单,增加一个master,就讲其他master的hash slot移出部分过去,减少一个master,就将它的hash slot移动到其他的master上。任何一台机器宕机,另外两个节点互不影响。因为key找的是hash slot不是机器
redis线程模型
redis内部使用文本事件处理器 file event handler
。这个文本事件处理器是单线程的,所以说redis的工作模式是单线程的。它采用IO多路复用机制监听多个socket,将产生事件的socket压入内存队列中,时间分派器根据socket上的事件类型来选择对应的时间处理器进行处理;
文本事件处理器包含四个部分:
- 多个socket
- 多路IO复用
- 文本事件分派器
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
redis 单线程模型也能效率这么高?
- 纯内存操作
- 核心是基于非阻塞的 IO 多路复用机制
单线程反而避免了多线程的频繁上下文切换问题
dubbo与springcloud的比较
- dubbo是通过二进制传输,占用宽带资源较少;springcloud是通过rest+json传输的,所以在性能上面,dubbo要优于springcloud;
- 在多数情况下,dubbo使用的是长连接小数据量的模式工作的,少部分情况下使用的短连接大数据量的工作模式
redis持久化
参考链接
RDB(bgsave)
RDB 是 Redis默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis重启会通过加载dump.rdb文件恢复数据。AOF
分布式事务
- 理论
2pc
在2PC的理论中,需要引入一个人协调者来统一掌控所有参与者的操作结果;整个过程有两个阶段
- 投票阶段;在投票的阶段中,参与者必须回复协调者,如果其中有一个参与者没有回复,整个阶段将处于阻塞的状态;
- 提交阶段;将所有参与者的回复提交给其他的参与者;在这个阶段,不仅要锁住所有所有参与者的资源还得锁住协调者资源
2pc知识一个理论,效率很低
- tcc
消息最大努力交互
RPC
- 定义
- RPC主要功能目标是让构建分布式计算更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性
- 调用方式
- 同步调用:客户端等待调用执行完后并返回结果。
- 异步调用:客户方调用后不用等待执行结果返回,但依然可以通过回调通知等方式获取返回结果
- 结构拆解
RPC服务器通过RPC server去导出远程接口方法,客户方import的方式去引入远程接口方法。客户方像调用本地方法一样调用远程接口方法,RPC框架提供接口的代理实现,实际的调用委托给代理RPCProxy。代理封装调用信息并将调用交给RpcInvoker去实际执行。再客户端的RpcInvoker通过连接器RpcConncecttor去维持与客户端的通道RpcChannel,并使用RpcProtocol执行协议编码并将编码后的请求消息通过通道发给服务方。Rpc服务端接收器RpcAcceptor接收客户端的调用请求,同样使用Rpcprotocol执行协议解码,并将解码后的信息传递给rpcprocessor去控制处理调用过程,最后委托调用Rpcinvoker去执行并返回调用结果。 - 主要组件
- RpcServer: 负责导出(export)远程接口
- RpcClient:负责导入(import)远程接口的代理实现
- RpcInvoker:
- 客户方实现:负责编码调用信息和发送调用请求到服务方并等待结果返回(同步)
- 服务方实现:负责调用服务端接口的具体实现并返回调用结果
- RpcProtocol:负责协议编码/解码
- RpcConnector:负责维护客户方与服务方的连接通道和发送数据到服务方。
- RpcAcceptor:负责接收客户方请求并返回请求结果
- RpcProcessor:负责在服务方控制调用过程,包括姑是哪里调用线程池,超时时间等。
RpcChannel:数据传输通道。
equals() 与 hashcode()
- 为什么重写了equals方法必须重写hashcode方法
相等的对象必须具有相等的散列码。- 覆盖equals方法时,需要遵循以下通用准则
- 自反性
对于任意非null的引用值x,x.equals(x)必须返回true。 - 对称性
对于任意非null的引用值x、y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。 - 一致性性
对于任意非null的引用值x、y,只要equals方法的比较操作在对象中所用的信息没有发生改变,那么多次调用x.equals(y)应该一致的返回true或false。 - 传递性
对于任意非null的引用值x、y、z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)必须返回true。
- 自反性
- hashcode在java中的通用准则
- 在应用运行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么多次调用该对象的equals方法应该始终如一的返回同一个整数。在同一个应用程序的多次执行过程中,每次执行equals方法所返回的整数可以不一致。
- 如果两个对象使用equals(Object)方法比较是相等的,那么调用这两个对象中的任意一个对象的hashCode方法都必须产生相同的一个整数结果。 重写equals方法就必须重写hashcode方法的原因
如果两个对象使用equals(Object)方法比较是不相等的,那么调用这两个对象中的任意一个对象的hashCode方法,则不一定要产生不同的整数结果。如果给不同的对象产生不同的hash码,有可能提高散列表性能(比如往HashMap中添加数据时,具体添加到哪个桶中,就是根据(table.length - 1) & hash来计算的)。
JWT安全性问题
对比于 session和cookie安全性,在获取到cookie或者session后,做不了数据被篡改和循环调用的防范措施
JWT如何防止篡改数据
- 覆盖equals方法时,需要遵循以下通用准则
- JWT的组成部分
- header(头部),头部信息主要包括(参数的类型--JWT,签名的算法--HS256)
{ "typ": "JWT", "alg": "HS256" }
- poyload(负荷),负荷基本就是自己想要存放的信息(因为信息会暴露,不应该在载荷里面加入任何敏感的数据),有两个形式,
{ "iss": "John Wu JWT", "iat": 1441593502, "exp": 1441594722, "aud": "www.example.com", "sub": "jrocket@example.com", "from_user": "B", "target_user": "A" }
sign(签名): 将前面两个编码后的字符串用
.
拼装在一起,然后将拼接完后的字符串用header标识的 HS256
进行加密,在加密的时候,我们还需要提供一个密钥(secret) 签名的作用就是为了防止恶意篡改数据。只要加密密钥不丢失,就不能踹改请求数据JWT如何防止在token丢失的情况下重复请求
可以在playload中加入时间戳并且前后端都来参与解决。
```
- 前端生成token时,在payload里增加当前时间戳
- 后端接收后,对解析出来的时间戳和当前时间进行判断
如果相差特定时间内(比如2秒),允许请求否则判定为重复攻击
```基础
面向对象
面向对象是模型化的,只要抽象出一个类,里面就有数据和解决问题的方法。需要什么功能直接使用就可以,用户不需要怎么去实现的
面向对象的三大特性:- 封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。 - 继承
提高代码复用性;继承是多态的前提。 多态
父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
线程相关
相关概念
- 并发
多个任务在同一时间段内执行。这些任务不是顺序执行的,而是以交替的方式被执行 - 并行
多个任务在同一时刻被执行
synchronized 作用域
synchronized的作用域分为 类锁
,对象锁
- 类锁(针对这个类)
- 类锁需要
synchronized 来修饰静态 static 方法
,写法如下java public static synchronized void test(){ // TODO }
- 使用代码块,需引用当前的类
java public static void test(){ synchronized (TestSynchronized.class) { // TODO } }
类锁和对象锁其实是一样的,由于静态方法是类所有对象共用的,所以进行同步后,该静态方法的锁也是所有对象唯一的。每次只能有一个线程来访问对象的该非静态同步方法。 类锁和对象锁是不一样的锁,是互相独立的
- 对象锁 (针对new出来的对象)
- synchronized修饰的非静态方法,修饰实例方法时,锁定的是当前对象
java public synchronized void test(){ // TODO }
代码块使用 synchronized 修饰的写法,使用代码块,如果传入的参数是 this,那么锁定的也是当前的对象
java public void test(){ synchronized (this) { // TODO } }
同步能够使得一个线程执行完毕后,另一个线程才开始执行线程同步和线程安全的区别
- 线程同步
线程同步更强调的是多个线程间的执行顺序 线程安全
线程安全更加强调的是对资源的访问控制实现线程同步有哪些方式
ConcurrentHashMap线程安全
转载于:https://www.cnblogs.com/KevinStark/p/10469305.html
最后
以上就是霸气大象为你收集整理的知识整理的全部内容,希望文章能够帮你解决知识整理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复