epoll

Pika源码学习--pika的通信和线程模型

 ̄綄美尐妖づ 提交于 2020-05-05 08:42:12
pika的线程模型有官方的wiki介绍https://github.com/Qihoo360/pika/wiki/pika-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B,这里主要介绍了pika都有哪些线程,这些线程用来干嘛。本篇文章主要涉及监听线程DispatchThread、IO工作线程WorkerThread和工作线程池ThreadPool,结合代码介绍里面实现的一些细节。 1.监听线程DispatchThread 在创建PikaServer的时候,会构造一个PikaDispatchThread,这个PikaDispatchThread,实际上是用了pink网络库的DispatchThread::DispatchThread DispatchThread构造函数里面会初始化好若干个WorkerThread DispatchThread继承自ServerThread,ServerThread继承了Thread,线程启动时实际上运行的是子类的ThreadMain方法,继承了Thread类的子类需要有自己的ThreadMain,监听线程start的时候,入口是ServerThread::ThreadMain()。线程启动会先ServerThread::InitHandle(),绑定和监听端口,下面看看ServerThread::ThreadMain(

聊聊select, poll 和 epoll

荒凉一梦 提交于 2020-05-04 11:52:21
聊聊select, poll 和 epoll 假设项目上需要实现一个TCP的客户端和服务器从而进行跨机器的数据收发,我们很可能翻阅一些资料,然后写出如下的代码。 服务端 void func( int sockfd) { char buff[MAX]; int n; // infinite loop for chat for (;;) { bzero(buff, MAX); // read the message from client and copy it in buffer read(sockfd, buff, sizeof (buff)); // print buffer which contains the client contents printf( " From client: %s\t To client : " , buff); bzero(buff, MAX); n = 0 ; // copy server message in the buffer while ((buff[n++] = getchar()) != ' \n ' ) ; // and send that buffer to client write(sockfd, buff, sizeof (buff)); // if msg contains "Exit" then server exit

聊聊select, poll 和 epoll_wait

岁酱吖の 提交于 2020-05-04 09:36:35
聊聊select, poll 和 epoll 假设项目上需要实现一个TCP的客户端和服务器从而进行跨机器的数据收发,我们很可能翻阅一些资料,然后写出如下的代码。 服务端 View Code 客户端 View Code 那么问题来了,如果有一个新的需求进来,现在需要你这个服务器程序同时支持多个客户端连接,你怎么办么呢?对的,这就引出了本文要聊的IO多路复用技术。 select,poll,epoll select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。 select int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据可读、可写

Netty 与三种 I/O 模式

半世苍凉 提交于 2020-04-29 14:23:28
Netty 与三种 I/O 模式 经典的三种 I/O 模式 生活场景: 当我们去饭店吃饭时: 食堂排队打饭模式:排队在窗口,打好才走; 点单/等待被叫模式:等待被叫,好了自己去端; 包厢模式:点单后菜直接被端上桌。 Netty 对三种 I/O 模式的支持 为什么 Netty 仅支持 NIO 了? 为什么 Netty 有多种 NIO 实现? 通用的 NIO 实现(Common)在 Linux 下也是使用 epoll,为什么自己单独实现? 实现的更好! NIO 暴露了更多的可控参数,例如: JDK 的 NIO 默认实现是水平触发。 Netty 是边缘触发(默认)和水平触发可切换。 Netty 实现的垃圾回收更少、性能更好。 NIO 一定优于 BIO 吗? BIO 代码简单。 特定场景:连接数少,并发度低,BIO 性能不输 NIO。 来源: oschina 链接: https://my.oschina.net/u/4370811/blog/4258262

Netty 与三种 I/O 模式

别说谁变了你拦得住时间么 提交于 2020-04-29 12:26:39
Netty 与三种 I/O 模式 经典的三种 I/O 模式 生活场景: 当我们去饭店吃饭时: 食堂排队打饭模式:排队在窗口,打好才走; 点单/等待被叫模式:等待被叫,好了自己去端; 包厢模式:点单后菜直接被端上桌。 Netty 对三种 I/O 模式的支持 为什么 Netty 仅支持 NIO 了? 为什么 Netty 有多种 NIO 实现? 通用的 NIO 实现(Common)在 Linux 下也是使用 epoll,为什么自己单独实现? 实现的更好! NIO 暴露了更多的可控参数,例如: JDK 的 NIO 默认实现是水平触发。 Netty 是边缘触发(默认)和水平触发可切换。 Netty 实现的垃圾回收更少、性能更好。 NIO 一定优于 BIO 吗? BIO 代码简单。 特定场景:连接数少,并发度低,BIO 性能不输 NIO。 来源: oschina 链接: https://my.oschina.net/u/4273264/blog/4258035

【2020Python修炼记】python并发编程(八)IO模型

人盡茶涼 提交于 2020-04-29 09:30:54
【目录】 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 异步IO(Asynchronous I/O) 六 IO模型比较分析 七 selectors模块 本文讨论的背景是Linux环境下的network IO 一、 IO模型介绍 回顾: 同步/异步 阻塞/非阻塞 1、IO分类 同步(synchronous) IO 异步(asynchronous) IO 阻塞(blocking) IO 非阻塞(non-blocking)IO 2、IO模型 五种IO Model: * blocking IO、 * nonblocking IO、* IO multiplexing 、* signal driven IO 、* asynchronous IO (由于signal driven IO(信号驱动IO)在实际中并不常用,所以主要介绍其余四种 IO Model) 3、IO发生时涉及的对象和步骤 对于一个network IO (这里我们以read举例),它会涉及到两个系统对象—— 一个是 调用这个IO的process (or thread),另一个就是 系统内核(kernel)。 当一个read操作发生时,该操作会经历两个阶段: #1)等待数据准备 (Waiting for the

redis为什么设计成单线程并且还这么快?

北城以北 提交于 2020-04-28 09:53:50
一、前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”、什么是“热数据和冷数据”,复杂一点的会问到缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题,这些看似不常见的概念,都与我们的缓存服务器相关,一般常用的缓存服务器有Redis、Memcached等,而笔者目前最常用的也只有Redis这一种。 如果你在以前面试的时候还没有遇到过面试官问你《为什么说Redis是单线程的以及Redis为什么这么快!》,那么你看到这篇文章的时候,你应该觉得是一件很幸运的事情!如果你刚好是一位高逼格的面试官,你也可以拿这道题去面试对面“望穿秋水”般的小伙伴,测试一下他的掌握程度。 好啦!步入正题!我们先探讨一下Redis是什么,Redis为什么这么快、然后在探讨一下为什么Redis是单线程的? 二、Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(Strings),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)与范围查询,Bitmaps,Hyperloglogs 和地理空间(Geospatial)索引半径查询。其中常见的数据结构类型有:String、List、Set、Hash、ZSet这5种。 Redis 内置了复制

redis为什么是单线程而且速度快?

与世无争的帅哥 提交于 2020-04-28 09:48:42
redis支持的5种数据类型:   1.String(字符串)   2.List(数组或列表)   3.Set(集合)   4.Hash(哈希或字典)   5.ZSet(有序集合) 数据库的工作模式按存储方式可分为:   硬盘数据库和内存数据库。Redis 将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快。 Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。 那么为什么Redis是单线程的?   官方解释是因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦!)。看到这里,你可能会气哭!本以为会有什么重大的技术要点才使得Redis使用单线程就可以这么快,没想到就是一句官方看似糊弄我们的回答!但是,我们已经可以很清楚的解释了为什么Redis这么快,并且正是由于在单线程模式的情况下已经很快了,就没有必要在使用多线程了! 但是,我们使用单线程的方式是无法发挥多核CPU 性能,不过我们可以通过在单机开多个Redis 实例来完善! 注意:   这里我们一直在强调的单线程

为什么redis是单线程的以及为什么这么快?

谁说我不能喝 提交于 2020-04-28 08:37:56
官网的说法 我们先来认真看一下官网的说法。翻译过来大意如下: CPU并不是您使用Redis的瓶颈,因为通常Redis要么受内存限制,要么受网络限制。例如,使用在一般Linux系统上运行的流水线Redis每秒可以发送一百万个请求,因此,如果您的应用程序主要使用O(N)或O(log(N))命令,则几乎不会使用过多的CPU 。 但是,为了最大程度地利用CPU,您可以在同一服务器上启动多个Redis实例,并将它们视为不同的服务器。在某个时候,单个实例可能还不够,因此,如果您要使用多个CPU,则可以开始考虑更早地分片的某种方法。 但是,在Redis 4.0中,我们开始使Redis具有更多线程。目前,这仅限于在后台删除对象,以及阻止通过Redis模块实现的命令。对于将来的版本,计划是使Redis越来越线程化。 既然redis的瓶颈不是cpu,那么在单线程可以实现的情况下,自然就使用单线程了。 自己的解读 我们知道redis是基于内存的。那么我们接下来要了解一个问题多线程cpu和内存直接操作差多少? 多线程操作就是使用多个cpu模拟多个线程,对redis进行操作。这样会造成一个巨大的问题,就是cpu的上下文切换问题。cpu的上下文切换的效率比直接在内存中进行读取差的很多。redis使用单个cpu绑定一个内存,针对内存的处理就是单线程的,这样避免了上下文的切换,所以非常的快。

nginx&http 第三章 惊群

▼魔方 西西 提交于 2020-04-27 21:15:02
惊群:概念就不解释了。 直接说正题:惊群问题一般出现在那些web服务器上,Linux系统有个经典的accept惊群问题,这个问题现在已经在内核曾经得以解决,具体来讲就是当有新的连接进入到accept队列的时候,内核唤醒且仅唤醒一个进程来处理。 /* * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve * number) then we wake all the non-exclusive tasks and one exclusive task. * * There are circumstances in which we can try to wake a task which has already * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns * zero in this (rare) case, and we handle it by continuing to scan the queue. */ static