系统调用流程
BIO
#最古老的多线程解决多客户端连接问题
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TestSocket {
public static void main(String[] args) throws IOException {
#启动一个服务端绑定一个端口8090
ServerSocket server = new ServerSocket(8090);
System.out.println("step1: new ServerSocket(8090)");
#死循环,不同时刻接受客户端的连接
while (true){
#每循环一次就接受一个客户端连接进来
Socket client = server.accept();
System.out.println("step2:client\t" + client.getPort());
#如果直接客户端I/O直接读的话会与client阻塞,创建新的线程
new Thread(()->{
try {
InputStream in = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true){
System.out.println(reader.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
1、运行java代码,并追踪线程
2、查看追踪文件
3、本地连接server:8090后,新建socket连接
4、深入内核查看
vim ooxx.25785 (主进程号)
可以看到有一个accept的内核调用方法,与java类似,java包装的
man accept
man 2 bind
java代码与内核调用有一种映射关系
多连接观察
1、观察现在主进程日志
2、再次添加一个连接
nc localhost 8090
再添加一个nc连接
非阻塞NIO
man socket
man 2 select
man epoll
非阻塞
查看nginx
3259
3260 master
3261 worker
worker就是等待着客户端来,来了之后才干活,不然就阻塞着
查看redis
单线程的redis
轮询线程
为啥不阻塞是轮询
redis只有一个线程,要干很多事情,epoll
比如LRU、LFU、RDB、AOF
kafka
0拷贝