nio,epoll,多路复用 —— 网络直播课笔记

nio,epoll,多路复用

IO   BIO    NIO
网络 socket  IO  BIO  NIO  多路复用器  ——> 学习 nginx redis netty tomcat

linux  strace -ff捕捉到java一个线程还是多线程  -o捕捉内容写入临时文件    追踪捕捉进程线程调用的系统内核调用

strace -ff -o out /usr/java/j2sdk1.4.2/bin/java TestSocket

jps  能看到服务和PID
socket四元组,本地IP端口号,异地IP端口号
set nu 显示行数
vi 
bind()系统内核调用方法
man 2 socket

java中的new ServerSocket 转化为 linux的几个方法——>socket,bind,listen,accept(3,阻塞了
28756主线程在监听
3监听的状态,8090端口
java jdk用C语言开发的,离不开C代码,java写的代码最终是用linux内核解释

tail -f out.28756  显示文件最后十行
nc localhost 8090 客户端链接
lsof 看进程状态
accept 3 返回了5连接上为文件描述符

new Thread ——>linux中为clone()=28994线程
cd /proc/28756/task 虚拟目录进程ID号
jps看到线程
cd task看到了进程中的线程,有一些内存共享
线程栈或进程栈是共享的

nc localhost 8090  多连接了一个线程29041
vi out.29041
recv(6,子线程在recv接收数据

28756主线程在等待客户端链接
lsof -p 28756  看到有5,6,7三个客户端连接

BIO的过程:
app(tomcat, netty, ngix)(服务端监听, while(true)接收,返回后new Thread)——>内核交互,sokcet(),bind(),listen(),accept(3,---阻塞,----接到客户端后抛出一个线程返回 = 5
——> recv(5,阻塞
int listen(int sokfd, int backlog最大连接数)

BIO弊端:每客户端  每线程,会抛出很多连接会有很多线程,C10K问题,需要有1万个线程,java线程就是一个操作系统进程,几个CPU的话,CPU有很多调度,浪费资源,连接数比较多的时候。4核心就4个连接8个连接模型可以满足
【阻塞】是致命的,需要阻塞变为非阻塞
程序员依赖kernel linux  ——>内核要提供非阻塞的能力, kernel nonblock

socketNIO  引入java nio包
NIO——>java new
       ——>linux nonblocking
serversocketchannel ss = serversocketchannel.open();
ss.bind();
ss.configureBlocking();
socketchannel client = ss.accept()不会阻塞直接返回,返回两种状态-1还是文件描述符
读也不会阻塞 返回 = 5 -1
read(5, 返回 N 0 -1

非阻塞——>accept,read,write, -1 不会卡住

NIO C10K ,一个线程接收读取遍历,或者4个CPU各负责2500个线程

NIO C10K
弊端 1个线程 用户态,内核态切换的过程成本高,1万个连接,1个人发来了数据,但是你在一个循环里,全量遍历O(n)的复杂度系统调用
程序和内核离得比较远,交互成本高

计算机软件工程学,批量

多路复用器,1万条路复用一个电话
int select()内核 允许程序监控多个文件描述符,等待一个或多个文件描述符达到可用的状态
多路复用select,epoll
过程:
socket,listen
while(true)
先调一个select(3)
accept(3) = 5 ——> select(3, 5)
accept(3) = 6 ——> recv(5) ——> select(3, 5, 6)
select(3,5,6,7,8,9,10) O(1)
recv(5) O(m)
多路复用器(select ,poll, epoll),只能给app返回状态,不能够读取数据
程序自己需要调用 R/W 你的IO
软件工程学——>同步【IO】模型,无论是在当前线程还是其他线程,程序自己读写(NIO,BIO),java里的IO模型多是同步的

异步【IO】模型,没有阻塞
调用了内核的一个方法(callback)(内核帮你把数据读写)IOCP程序里不需要维护读写的过程

select 1024fd
poll没有数量限制,本质是一样的  select poll是一类
EPOLL 多路复用器,同步模型

select poll弊端:
每循环都重复传递数据
每次调用内核需要遍历用户传递的参数
本质是内核没有留存过数据

解决方法内核开辟空间,减少传递参数,加上中断,中断事件,调用的时候直接给结果集不用传递

man epoll
epoll_create(2),epoll_ctl(2)
man epoll_create
return value 返回一个文件描述符

epoll_ctl(epfd, op)
epoll_waite
app
socket, bind, listen
epoll_create = 5描述符内核开辟了一个空间为5
kernel 5 
——>epoll_ctl(5, ADD, 3监听的
——>while(true) epoll_wait(5,*指针数据集合) //select(3,5,6,7,8)
——>accept(3) = 6新的客户端6
——>epoll_ctl(5, ADD, 6, read)
——>read(5)

kernel ——>5fd
                     3,accept——>epoll_wait()

异步为一种事件上的异步,整个的IO模型是同步的

从上到下贯穿的一个问题资源利用率的问题

java中包装了selector多路复用器为linux中的select,poll,epoll三种

ServerSocket
selecter.open()
server.register(selecter, selectKey.op_accept)
selector.select()就是select或者epoll_wait

启动的时候选参数可以设置为什么多路复用器
ngix根据内核优选选择是poll还是epoll

yum install streace
redis,nginx都用epoll
service nginx stop
strace -ff -o out  ./nginx
ps -fe | grep nginx
vi out.29385
bind(6) = 0 监听
vi out.29386 
vi out.29387 worker
epoll_create()
epoll_ctl()
epoll_wait()

strace -ff -o out   /opt/bigdata/redis5/bin/redis
vi out.
epoll_create() - bind() - fcntl() - epoll_ctl()
lsof -p $$ 文件描述符
lsof -p 3947

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值