# netty_study **Repository Path**: guyandog/netty_study ## Basic Information - **Project Name**: netty_study - **Description**: No description available - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-02-12 - **Last Updated**: 2024-11-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 精品:[how to do distributed locking](http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html) netty做长连接 SpringCGlib动态代理 不需要配置 zookeeper客户端使用curator 随机负载均衡 netty默认是边缘触发 jdk是水平触发 水平触发:如果文件描述符已经就绪可以非阻塞的执行IO操作了, 此时会触发通知.允许在任意时刻重复检测IO的状态, 没有必要每次描述符就绪后尽可能多的执行IO.select,poll就属于水平触发. 边缘触发:如果文件描述符自上次状态改变后有新的IO活动到来, 此时会触发通知.在收到一个IO事件通知后要尽可能多的执行IO操作, 因为如果在一次通知中没有执行完IO那么就需要等到下一次新的IO活动到来才能获取到就绪的描述符.信号驱动式IO就属于边缘触发. 提升效率 缓冲区构建 堆缓冲区 常用的ByteBuf模式是将数据存储在JVM的对空间中,这种模式称之为 支撑数组,在没有池化的情况下快读分配和释放, ByteBuf byteBuf = ... if (byteBuf.hasArray()){ //获取字节数组头节点 byte[] array = byteBuf.array(); //可读字节长度 int len = byteBuf.readableBytes(); //获取第一个字节的偏移量 int i = byteBuf.arrayOffset() + byteBuf.readerIndex(); } ######当hasArray()返回false时候,将会触发UnsupportedOperationException 直接缓冲区 ByteBuffer可以直接通过本地调用分配内存, 避免在每次调用本地IO操作之前将缓冲区的内容 赋值到一个中间缓冲区,导致速率变慢 复合缓冲区 ByteBuf提供一个聚合视图,可以添加和删除ByteBuf CompositeByteBuf 复用同一个数据区域,提高效率 ``` // Use an array to hold the message parts ByteBuffer[] message = new ByteBuffer[] { header, body }; // Create a new ByteBuffer and use copy to merge the header and body ByteBuffer message2 = ByteBuffer.allocate(header.remaining() + body.remaining()); message2.put(header); message2.put(body); message2.flip(); ``` ByteBuf有两个索引 读索引 写索引,将内存区域化为三个区域 0 readIndex writeIndex capacity 丢弃字节区域 可读字节区域 可写字节区域 派生缓冲区 ####创建缓冲区方法 duplicate() slice() slice(int,int) Unpooled.unmodifiableBuffer() order(ByteOrder) readSlice(int) 返回新的ByteBuf实例,和ByteBuff是内存共享的,修改会导致其他ByteBuf一起被修改 channelHandler可以属于多个ChannelPipeline,可以绑定到 多个ChannelHandlerContext实例上,ChannelPipeline可以共享 一个ChannelHandler,需要再ChannelHandler使用@Sharable 多个线程添加ChannelHandler,添加注解使其线程安全 ##################################################################################### 关于SpringBoot循环依赖的问题 非正常: public class BeanB { private final BeanA beanA; public void setBeanA(BeanA beanA) { this.beanA = beanA; } } public class BeanA { private final BeanB beanB; public void setBeanB(BeanB beanB) { this.beanB = beanB; } } 正常 public class BeanB { @Autowired private BeanA beanA; public void setBeanA(BeanA beanA) { this.beanA = beanA; } } public class BeanA { @Autowired private BeanB beanB; public void setBeanB(BeanB beanB) { this.beanB = beanB; } } SpringBoot自动配置,实例化B后在Bean后置处理器中发现需要注入属性A,转去初始化A,注入B又发现依赖A,导致依赖循环 答案在这段源码里面: /** * Return the (raw) singleton object registered under the given name. *
Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } singletonObjects: 完成初始化的单例对象的 cache,这里的 bean 经历过 实例化->属性填充->初始化 以及各种后置处理(一级缓存)。 earlySingletonObjects: 存放原始的 bean 对象(完成实例化但是尚未填充属性和初始化),仅仅能作为指针提前曝光, 被其他 bean 所引用,用于解决循环依赖的 (二级缓存)。 singletonFactories: 在 bean 实例化完之后,属性填充以及初始化之前,如果允许提前曝光, Spring 会将实例化后的 bean 提前曝光,也就是把该 bean 转换成 beanFactory 并加入到 singletonFactories(三级缓存)。 @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference 二级缓存就可以解决循环依赖问题,为什么还要加个singletonFactories三级缓存,闲的蛋疼吗 三级缓存的作用: /** * Obtain a reference for early access to the specified bean, * typically for the purpose of resolving a circular reference. * @param beanName the name of the bean (for error handling purposes) * @param mbd the merged bean definition for the bean * @param bean the raw bean instance * @return the object to expose as bean reference */ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; } #####################################################################################