2.4 网络设计与redis、memcached、nginx组件


在这里插入图片描述

一、网络模块需要处理哪些事情

网络编程主要关注客户端与服务端交互的四个问题:
1、连接建立
2、消息到达
3、消息发送
4、连接断开
在这里插入图片描述
以上四个问题归结到底是网络IO,IO函数主要有两个作用:
1、检测IO是否就绪
2、进行IO操作—accept、connect、read、write

accept、connect是关于网络的连接建立。accept检测全连接队列中是否有数据,如果有则从中取出一个节点,返回一个对象clientfd,以及客户端的IP地址。connect是对于客户端而言,如果客户端收到ACK,即连接建立成功。(对应三次握手)
在这里插入图片描述
read是把数据从内核态read buffe拷贝到用户态中,当期为0代表read buffer中读到EOF
write是把数据从用户态拷贝到内核态write buffe中
在这里插入图片描述
读和写的区分:以“读书”和“写字”为例子。所谓读书:就是书籍上的文字通过人的视觉系统,经神经系统在大脑里产生主观映像;写字就是大脑里产生的主观映像通过神经系统控制运动器官——手在纸上写出字。“读”与“写”是把大脑作为中心,由外界向中心输入,就是“读”;由中心向外界输出就是“写”。现在“读”与“写”的问题就变成了输入和输出的关系了。
以电脑CPU为中心。从外界的设备(键盘,磁盘等等)向CPU传递信息就是“读操作”,由CPU向外界设备(屏幕,磁盘等等)传递信息就是“写操作”。
例如对于全双工通信的TCP协议
在这里插入图片描述

二、reactor网络设计模型

IO多路复用的主要功能是检测多条连接的IO是否就绪,但不具备具体IO操作的功能(比如读写数据)。常见的IO多路复用器有select、poll,epoll,他们是对IO的管理,检测接入的IO,触发IO事件;注意这三个都是同步IO。

reactor网络设计模型是把IO就绪检测的功能交由IO多路复用器实现,针对事件进行进行IO操作,不同的事件调用不同的回调函数。

int nready = epoll_wait(reactor.epfd, events, EVENTS_LEN, timeouts);
int i = 0;
for (i=0; i< nready; i++){
	if (events[i].events & EPOLLIN){//触发读事件

		listenfd --> 新连接到达--> accept
		clientfd --> 这条连接发送了数据 --> read

	}else{ //触发写事件

		connectfd --> 连接建立成功,可向第三方(如数据库)发送数据
		clientfd -->  这条连接写缓冲区可写 -->write

	}
}

之所以把IO就绪检测的功能交由IO多路复用器,是因为对于服务端而言,某一时刻只有少量的连接有数据交互,如果让IO函数自己检测,在阻塞IO时,每个连接都需要一个线程;非阻塞IO时,每个连接都需要通过while在应用层进行检测。

三、网络模块与业务的关系

在这里插入图片描述

  1. 创建socket,生成listenfd,通过bind绑定,通过listen监听。
  2. 把listenfd注册到reactor,注册读事件(客户端与服务端建立连接)。
  3. 如果listenfd读事件触发,调用accept接收连接生成clientfd,然后把clientfd注册到reactor中,注册读事件(客户端向服务端发送数据)。
  4. 当客户端发送数据时,会触发clientfd写事件相应的回调函数。 读数据—解析(协议)数据—处理业务相关的计算—加密打包—回复数据

四、redis、memcached、nginx

1、redis

redis采用了事件驱动的模型,在启动时会创建一个I/O多路复用的事件处理器(即reactor),然后将所有客户端请求都注册到该事件处理器中。当有新连接到达或者已有连接有数据可读写时,事件处理器就会触发相应的回调函数进行处理。

由于redis是单线程运行的,因此只需要一个reactor即可满足其并发处理需求。通过合理地利用CPU资源和异步非阻塞IO技术,redis可以实现高效地处理大量并发请求。
在这里插入图片描述
需要注意的是,当Redis遇到某些长时间执行的命令时,可能会导致其他请求被阻塞而影响整个系统性能。比如三个客户端同时向服务端发送数据,服务端是按先后顺序接收处理。这种就会出现如果先到的数据处理比较耗时,会导致后续客户端出现饥饿现象。优化方式是:
1、如果IO耗时,把IO操作放到IO线程池处理,主线程处理computer。
2、如果computer耗时,采用分治思想或者不同时间复杂度的算法

2、memcached

memcached是一个基于事件驱动的内存缓存服务器,它使用多个reactor来处理并发连接。

具体来说,memcached使用一个主线程和多个工作线程。每个工作线程都有自己的reactor,用于处理客户端连接和请求。当有新连接到达时,主线程会将其分配给某个工作线程,并且该工作线程的reactor会负责处理这个连接的所有事件。

在默认情况下,memcached的工作线程数等于CPU核心数。
在这里插入图片描述

3、ngnix

Nginx是一个基于事件驱动的服务器,它通过多个reactor处理并发连接。

具体来说,Nginx使用一个主进程和多个worker进程。每个worker进程都有自己的reactor,用于处理客户端连接和请求。当有新连接到达时,主进程会将其分配给某个worker进程,并且该worker进程的reactor会负责处理这个连接的所有事件。

在默认情况下,Nginx的worker进程数等于CPU核心数。
在这里插入图片描述

  1. 创建 Listenfd bind 监听
  2. worker 进程都有 Listenfd
  3. worker 进程争夺 accept 锁
  4. 谁争夺到了锁,谁就有接收新连接的权利
  5. 接收的连接放入该 worker

4、总结

redis是单线程单reactor,可以把IO放入线程池,也可以把业务计算部分放入线程池。
如果业务之间交互比较多,但加锁简单,可以用多线程memcached
如果业务之间交互比较少,可以用多进程ngnix

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲谈社

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值