面试:中断:Close_Wait:进程内存:ES优化
计算机执行中断过程描述
中断是一种使CPU中止正在执行的程序而转去处理特殊事件的操作;
所以这个过程一定引起处理器的上下文的切换;
中断分为两种:硬件中断,软件中断;
中断的作用:并行操作,硬件故障报警与处理,支持多道程序并发运行,提高计算机系统的运行效率,支持实时处理功能,提供故障现场处理手段,维持系统可靠正常工作;
中断的过程:
①中断源发出中断请求;
②判断当前处理机是否允许中断和该中断源是否被屏蔽;
③优先权排队;
④处理机执行完当前指令或当前指令无法执行完,则立即停止当前程序,保护断点地址和处理机当前状态,转入相应的中断服务程序;
⑤执行中断服务程序;
⑥恢复被保护的状态,执行“中断返回”指令回到被中断的程序或转入其他程序。
上述过程中前四项操作是由硬件完成的,后两项是由软件完成的。
线上大量CLOSE_WAIT的原因
为什么会出现大量的mysql连接是 CLOSE_WAIT 呢?
根据四次挥手,我们知道四次挥手有两个状态一个是Close_wait,一个是TimeWait;
TimeWait 出现在最后,客户端向服务端发送ack,表示确认,请求服务端回ack, 这是客户端会等待2MSL(报文最大生存时间)
Close_wait 出现在服务器向客户端第一次确认断开时,这是client无法向服务器发送消息,但是服务器还有消息向客户端发送;
大量的Close_wait 说明是服务器与客户端的连接没有断开;
使用 perf 把代码的调用链路;
数据为空的情况没有对事务进行回滚rollback,数据不为空的情况进行commit,导致服务端没有主动发起close。因此 MySQL负载均衡器 在达到 60s 的时候主动触发了close操作,但是通过tcp抓包发现,服务端并没有进行回应,这是因为代码中的事务没有处理,因此从而导致大量的端口、连接资源被占用;
Time_Wait 和 Close_Wait 产生原因与分析
Time_Wait
- 产生:调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态;
- 为什么要进行Time_wait?
Time_Wait 要等待2MSL(报文最大生存时间),为实现TCP全双工连接的可靠释放,为使旧的数据包在网络因过期而消失; - time_wait状态如何避免?首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。
问题:无法对外新建TCP连接时,线上服务器存在大量处于TIME_WAIT状态的TCP连接?
TIME_WAIT的典型持续时间为1-4分钟。
closeWait
close_wait的危害在于,在一个端口上打开的文件描述符超过一定数量,(在linux上默认是1024,可修改),新来的socket连接就无法建立了。
会报:Too many open files。
client 连接池有部分对象没有return;
linux 进程的内存分别
程序编译后生成的目标文件至少含有这三个段Text,Data,BSS,这三个段的大致结构图如下所示:

BSS段:在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。是静态内存分配;
数据段:在采用段式内存管理的架构中,数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
代码段:在采用段式内存管理的架构中,代码段(text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域属于只读。
堆是运行时程序动态申请的空间,属于程序运行时直接申请、释放的内存资源。
栈区用来存放函数的传入参数、临时变量,以及返回地址等数据。
JVM本质就是一个进程,因此其内存空间(也称之为运行时数据区,注意与JMM的区别)也有进程的一般特点。深入浅出 Java 中 JVM 内存管理,这篇参考下。
但是,JVM又不是一个普通的进程,其在内存空间上有许多崭新的特点,主要原因有两 个:
JVM将许多本来属于操作系统管理范畴的东西,移植到了JVM内部,目的在于减少系统调用的次数;
Java NIO,目的在于减少用于读写IO的系统调用的开销。JVM进程与普通进程内存模型比较如下图:

ES在数据量很大的情况下,如何提高查询效率?
ES 在搜索几亿条数据的时候,响应5~10s
- FileSystem Cache
往es里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 filesystem cache 里面去;

估计存储在ES中的数据量,尽量保证查询最大量数据都能在缓存能存下;其次是减少字段,将查询的字段存es,不查询的只做展示,已经ES + Hbase架构
- 数据预热
自己的后台系统去搜索一下热数据,刷到 filesystem cache 里去
- 冷热分离
大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。
确保热数据在被预热之后,尽量都让他们留在 filesystem os cache 里,别让冷数据给冲刷掉。
- 字段设计
最好是先在 Java 系统里就完成关联,将关联好的数据直接写入 es 中。搜索的时候,就不需要利用 es 的搜索语法来完成 join 之类的关联搜索了。
-
分页优化
-
最多允许查10000条数据的分页
-
scroll 会一次性给你生成所有数据的一个快照,然后每次翻页就是通过游标移动, 唯一的一点就是,这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场景。