netty源码解读

ByteBuffer

bytebuffer的缺点:

1
2
3
4
5
1. bytebuffer长度固定,一旦分配完成,它的容量不能动态扩展和收缩,当需要编码的pojo object大于bytebuffer的容量时,不发生indexoutofbound exception

2. bytebuffer 只有一个标识位置的指针position, 读写的时候需要manually 调用flip()和rewind() 使用者需要小心调用这些api

3. bytebuffer的API功能有限,高级功能需要开发者自己实现

ByteBuf的工作原理

writeindex readindex discardReadBytes会发生字节数组的内存复制 调用可以节省内存,但是降低性能。

ByteBuf实现

HeapByteBuf

内存的分配和回收速度快,可以被jvm自动回收 缺点: 如果进行socket的i/o读写,需要额外做一次内存复制,将heap内存对应的buffer复制到内核channel中,性能会有一定成的下降

DirectByteBuf 直接内存

堆外内存,相比而言,它的分配和回收速度会慢一些,但是将它写入或者从socket channel中读取时,由于少了一次内存复制,速度比堆内存快

i/o通信线程的wirte/read缓冲区使用directByteBuf back-end的消息encoding和decoding用heapByteBuf

内存回收

对象池byteBuf

可以循环使用创建的bytebuf, 提升内存使用率

AbstractByBuf

写操作 4M 以内 倍增, 64byte -- 128byte 4M以后 步进,一次增加4MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Override
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
if (minNewCapacity < 0) {
throw new IllegalArgumentException("minNewCapacity: " + minNewCapacity + " (expected: 0+)");
}
if (minNewCapacity > maxCapacity) {
throw new IllegalArgumentException(String.format(
"minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
minNewCapacity, maxCapacity));
}
final int threshold = CALCULATE_THRESHOLD; // 4 MiB page

if (minNewCapacity == threshold) {
return threshold;
}

// If over threshold, do not double but just increase by threshold.
if (minNewCapacity > threshold) {
int newCapacity = minNewCapacity / threshold * threshold;
if (newCapacity > maxCapacity - threshold) {
newCapacity = maxCapacity;
} else {
newCapacity += threshold;
}
return newCapacity;
}

// Not over threshold. Double up to 4 MiB, starting from 64.
int newCapacity = 64;
while (newCapacity < minNewCapacity) {
newCapacity <<= 1;
}

return Math.min(newCapacity, maxCapacity);
}

CAS: compareAnsSet是由操作系统层面提供的原子操作

PooledByteBuf内存池原理分析

预先申请的那一块内存就被称为memory arena

Poolarena

poolChunk

chunk用来组织和管理多个page内存分配和释放 chunk中的page被构建成一颗binary tree

![](/Users/yifanguo/Desktop/屏幕快照 2018-07-25 19.20.31.png)

page的大小是4 byte chunk的大小是4*16

对树的遍历采用dfs,但是对哪个字节点继续遍历是随机的

ChannelPipeline 和 ChannelHandler

ChannelPipelin 和ChannelHandler机制类似于 servlet 和filter

servlet filter 可以声明的方式插入到http请求响应的处理过程中,用于拦截请求和响应,以便能够查看 提取或以某种方式 操作正在客户端和服务器之间的交换数据。

拦截器封装了业务定制逻辑,能够实现对web应用程序的预处理和事后处理

架构

![](/Users/yifanguo/Desktop/屏幕快照 2018-07-25 19.53.16.png)

链路有效性检测

由于长连接不需要每次发送消息都创建链路,也不需要在消息交互完成时关闭链路,因此相对于短连接性能更高

对于长连接,一旦链路建立成功便一直维系双方之间的链路,直到系统退出

为了保证长连接的链路有效性,往往需要通过心跳机制周期性的进行链路检测

java内存模型

![](/Users/yifanguo/Desktop/屏幕快照 2018-07-25 20.04.25.png)

CAS

互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能的额外损耗,因此这种同步被称为阻塞同步 它属于一种悲观的并发策略,悲观锁

非阻塞同步 乐观锁

java应用最广泛的非阻塞同步是CAS