整理
Posted v4ki5mqu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整理相关的知识,希望对你有一定的参考价值。
open:根据不同的底层操作系统创建不同的selector。windows采用的是poll方式,linux采用的是epoll方式。
register:将通道包装为selectKey,放入fdMap和pollWapper。
select:处理掉cancleKeys,调用pollWapper.poll,返回可读通道,可写通道,异常通道,根据poll返回结果更新selectKeys。
select返回之后:根据返回的publicSelectedKeys(selectKeys的用户视图,只能remove)轮询,根据通道事件做出动作。
线程安全实现
channel 包含keyLock和regLock来保证配置动作、注册动作、对keys的添加、移除等线程安全
selector 对自身、publicKeys、publicSelectedKeys加锁,保证seletor动作、处理canclekeys动作、关闭selector动作、register动作线程安全。
线程模型
nio是使用单线程selector来处理多个channel,如果一个channel处理事件很长,会影响到其他。应该考虑处理部分使用线程池来处理,不要把事务处理放到selector线程。
poll 和 epoll区别
poll模式下的select每次都需要将pollWapper做为参数传递到内核,然后内核轮询这些fd(内核也不知道那些fd是准备好了的)。返回发生了感兴趣事件的fd。
epoll 创建的时候epoll_create,会在系统中建立一个文件系统,一颗红黑树和一个就绪链表,并且和底层建立回调关系。epoll_ctl向epoll对象中添加fd。当有fd发生事件时,底层(网卡的中断程序)会调用回调,将这个fd加入到就序链表中。只需要调用epoll_wait将就绪好的fd返回就行。所以每次seletor动作只需要返回就绪列表中的fd就行了,无需轮询。也不需要传递pollWapper,因为文件系统中有。epoll模式下的select动作就是1、epoll_ctl,将fd加入到红黑树,如果红黑树有就返回,没有就加入并且在底层设置回调。2、epoll_wait,返回准备好的fd。
ThreadLocal内存泄漏
ThreadLocal在没有外部强引用时,发生GC时会被回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。
ZkMarshallingError: java.io.StreamCorruptedException zk反序列化错误 https://blog.csdn.net/y277an/...
https://blog.csdn.net/android... springboot优雅停止
https://blog.csdn.net/qq_3003... 异常的处理
springboot疑难杂症
一般建立springboot项目,pom文件中都会制动parent为spring-start,但是如果这个项目本身已经有了parent或者公司为了更好管理版本问题,在父模块的pom文件加入dependManager,在其中加入spring-depandies。
dependManager中指定的jar包子类必须申明才算导入了,但是可以不用指定版本。假设dependManager中制定了A B两个jar包。A包本身也依赖B,不指定B,也会导入B,指定B后,则A包不会在导入B,此时如果子模块申明了A,没有申明B,此时A中包缺少B包,会报错classNoDefinitionError。解决办法:将父模块中的B去掉,或者在子类中再申明B。
spring 4.X后不提供orm包了
zk监听的实现机制
现在我们的zookeeper客户端程序里面有一个main线程,然后在里面创建了一个zkclient,在这个时候就启动了两个线程。一个线程是Connector的客户端,用于和zookeeper连接去上传数据、请求数据等;还有一个线程是Listener,可以去调用我们代码里面的process方法,它会监听在一个端口。设置监听时,通过Connector通信线程告诉zookeeper我们监听器的通信IP和端口以及监听的path;zookeeper就会记录这些IP、端口、path,当path下的数据发生了变化,zookeeper就知道触发事件的客户端在哪里(通过IP和端口可以找到),然后可以通过socket通信也就是通过RPC去远程调用客户端,客户端收到事件就会去回调process方法。
zk脑裂
一、脑裂现象
脑裂现象主要是指当出现网络分区时,zookeeper集群形成了两个或者多个leader的情况,这时如果两个leader都提供服务,则会出现数据不一致问题。
二、集群出现分区的选举方式
当由于网络分区,集群被分离为多个子集群时,则此时原集群的leader失去了半数的follower节点,故需要重新进行leader选举。同时另外的子集群由于没有leader,故也会发起leader选举。此时就需要在可用性和数据一致性方面做出选择。
zookeeper针对这种情况,提供了一下三种机制来对可用性和数据一致性进行取舍。
- Quorums机制(超过半数)
即如果出现多个分区,则每个分区不满足超过总数的一半条件,所以要么只有一个leader,要么选举失败,这种方式是保持数据一致性,舍弃可用性的一种实现。 - Weight机制(加权机制)
通过Quorums机制只有超过半数才能提供服务,这样如果集群很大,出现分区则无法使用,故可以给节点设置权重,一些节点权重较高,这样计算出来超过一定权重值则也可以选举leader。
这种方式由于机器的权重不一样,故某些分区也是可以选举leader成功的,故可以继续提供服务,即保留可用性。所以可用性方面相对于Quorums机制是有提高的。 - Fencing机制(共享资源加锁机制)
集群节点可以看到共享资源说明在集群中,可以获取共享资源的锁则成为leader。
这种方式偏向于可用性,数据一致性较弱。
三、CP而非AP:数据一致性
针对以上3种方式,zookeeper默认是基于Quorums机制的,即只有超过半数follower的分区才可以选举出leader继续提供服务,如果选举不出来,则不可用。这种方式一定程度上保持了数据一致性,所以总体来说Zookeeper 是强调 CP,即数据一致性,而舍弃了 CAP 的 A,即高可用。
微服务框架的注册中心问题
在微服务架构中,对于注册中心,开源的Dubbo使用了Zookeeper,但是阿里内部却不推荐使用Zookeeper,并且微服务框架 SpringCloud 使用了 Eureka,而不是 Zookeeper 来作为注册中心,其中很大一部分原因就是微服务的注册中心是更加强调高可用,而非数据强一致性。
Buffer类的用法:
1.申请到了Bufffer后,直接可以执行写;
2.读操作的时候,flip;
3.如果想要重新读,rewind;
4.如果读了一部分,想要继续写,compact;
package study;
import io.netty.util.concurrent.FastThreadLocal;
public class FastThreadLocalStudy {
private static final FastThreadLocal<Integer> fastThreadLocal1 = new FastThreadLocal<Integer>() {
@Override
protected Integer initialValue() throws Exception {
return 100;
}
@Override
protected void onRemoval(Integer value) throws Exception {
System.out.println(value + ":我被删除了");
}
};
private static final FastThreadLocal<String> fastThreadLocal2 = new FastThreadLocal<String>() {
@Override
protected String initialValue() throws Exception {
return "haha";
}
@Override
protected void onRemoval(String value) throws Exception {
System.out.println(value + ":我被删除了");
}
};
public static void main(String[] args) {
fastThreadLocal1.get();
fastThreadLocal1.set(1);
ThreadLocal<String> s = new ThreadLocal<>();
}
}
以上是关于整理的主要内容,如果未能解决你的问题,请参考以下文章