重学swoole

距离上次学习swoole已经有很长一段时间了,也用swoole做过几个小服务。随着版本更新,swoole开发了很多新功能和新接口,本来一直想抽时间再系统的看一次,一直拖拖拉拉,这2天终于下定决心重新学习swoole,记录下来,备以后学习参考,按自己理解的,不一定都对。错误的后面修正



1.学习swoole需要具备哪些知识

很多开发者一来就装扩展,直接试demo,由于官网文档和版本问题,其实很多demo是测试不下去的,然后感觉很难,就放弃了。
https://wiki.swoole.com/wiki/page/487.html
上面列举了几项:

  • 多进程/多线程
  • SOCKET
  • TCP/IP网络协议
  • IO复用
  • 调试工具

既然要重新学,那就把这几项先重新研究一下,研究透彻。

多进程/多线程

进程和线程的概念必须整清楚。

执行一个程序,程序的实体就是进程,是资源分配的基本概念和调度的基本单位。简单来说,你执行一个可执行文件,这个就是启用了一个进程,多运行几次这个程序,就启用了多个进程

线程就是在这个程序执行的进程中,分配去执行任务的执行单位,一个进程可以创建多个线程去执行任务
所以一个可执行程序 ->可一、多个进程->一、多个线程

而swoole里面很重要的协程是在单个线程中,通过c和php的栈保存了程序的运行状态,通过调度器进行切换。为什么要设计这么个东西呢?

我理解的是:一个线程在执行程序的时候,需要从接口获取数据,得有网络开销,以前是阻塞的,程序得等到接口返回了,才能往下执行,那么如果一个程序依赖10个接口,每个接口耗时0.1秒,那么程序总共执行时间是多少呢?1秒+,那10万次呢 各位可以写个for循环10万次,访问一个接口试试。

因为一般情况下,程序是顺序执行,访问第一个请求的没有获得回复的时候,程序是等待起的,第二个请求要等第一个完成后才请求, 这个就是所谓的阻塞。 那么协程解决了什么问题呢?他可以不等待网络返回,把当前执行状态挂起,接着往下执行代码,等请求有返回了,再通过调度器回到之前挂起的执行状态执行。

首次看协程的朋友肯定会有很多疑惑,他怎么就知道是那个接口返回数据?怎么会我后面的代码都执行了?前面协程的代码怎么再次执行?这个就是后面几项需要了解的知识先别急, 这里你只要知道,协程可以挂起当前执行状态(程序堆栈,变量等等),然后可以再次触发切换到那里去执行即可。

看了上面协程的作用,那么我们再来看看刚才for循环10次请求需要多少时间呢?不错,就是相当与最长一次请求的时间,大概也是0.1秒,那我们循环10000次,需要多久呢?不错,也是0.1+ ,而php7性能已经足够强悍,加上swoole底层扩展的优化,所以swoole可以宣称高性能,1秒几十上百万请求都不在话下。

SOCKET

SOCKET中文名称套接字。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认,接受数据/发送数据,结束请求。socket编程就是针对这过程进行编程。通过调用系统底层提供的socket APi,你也可以写出socket服务

TCP/IP网络协议

包含了一系列构成互联网基础的网络协议,网上很多教程和书籍可以让你深入了解,这里不做赘述,我们要用到和明白的是,一个数据包传输过来了,我怎么解析这个包,根据哪个协议解析出来,比如一个包传过来,开头几行是什么意思,通过什么分割内容。比如http协议,一个请求消息类似与:

Host: download.*******.de
Accept: */*
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/4.04[en](Win95;I;Nav)
Range: bytes=554554-

那么根据http协议,第一个host是主机名,第二个、第三个等等只要按照协议规定的传输,那我这边就可以把这个请求按http协议解析出来,可以知道请求的各个参数。其他协议同理,浏览器也根据协议解析返回的包,那些是要渲染的,请求状态是多少等等

IO复用

首先i/o是什么?Input/Output,输入输出,一般指的i/o是指的 i/o流,流就是传输的数据。 这个数据如何传输就有5种IO模型
:阻塞,非阻塞,I/O复用,信号驱动,异步。 几个的区别和作用自己去网上搜下,或者看一本书<<Linux高性能服务器编程>>。

这里说下I/O复用这个神奇的魔法。一般情况下,一个I/O流进来,我们就开启一个进程处理这个I/O流。那么假设现在有一百万个I/O流进来,那我们就需要开启一百万个进程一一对应处理这些I/O流。 试问哪个服务器有这么刚健?

这个时候聪明的人设计了I/O复用,一个线程,通过记录I/O流的状态来同时管理多个I/O。用来提高服务器的吞吐能力,所以swoole的百万并发就是使用这个,解决了传统php-fpm的并发问题。

调试工具

这个没什么好说的,都是些工具,孰能生巧的。大致会官网提到的几个就行

  • 使用 gdb 调试Linux程序
  • 使用 strace 跟踪进程的系统调用
  • 使用 tcpdump 跟踪网络通信过程
  • 其他Linux系统工具,如ps、lsof、top、vmstat、netstat、sar、ss等

大部分刚接触异步编程的朋友会懵逼,因为这个之前一直开发的模式不一样,请求进来,执行代码,返回结果。一看到swoole就感觉理解不了, 程序会跳到中间去执行,而且程序执行完了(代码的最后一行执行了),代码隔会儿还会执行,而且他还是常驻内存,通过什么方式再次执行到程序某个流程上去?。 我记得我一次学swoole,还没怎么接触过异步编程就有个疑惑,swoole用协程执行异步后,swooled主代码的程序已经结束了,请求是怎么返回结果的?10万次请求进来后,他只管接受端口请求,然后调度执行,那些执行的结果怎么返回到前端的?

上面的疑惑要解决,就需要花大量时间去看下进程,线程,协程,理解TCP/IP网络协议,IO事件,IO复用。这个要写能出书,只有朋友们自己去理解了,刚学习的朋友,可以一步步来,首先明白上面说的即可,知道代码是可以挂起和唤醒的,单线程中可以通过I/O复用,记录跟踪每一个sock的状态,并不是之前传统模式下的一个请求->执行代码->一个返回。

ok基础不是一天练成的,需要花很多时间去理解和实践。当你感觉大致能理解这些基础了,学习swoole能事半功倍,不至于懵逼。


2.swoole学习

swoole的牛逼,node,go等的对比就不去吹了。安装和配置官网已经很详细了,我测试的用的php7.2, 安装swoole直接用pecl install swoole,选择要用的功能,然后修改php.ini即可。

学习前一定要去看https://wiki.swoole.com/wiki/page/p-server.html,记住理解几张图,至少你得有个大致的印象和概念,如果你连运行流程都不知道,那他的各个接口和功能就不知所云了。

swoole提供的主要有Server,HttpServer,WebSocketServer,Coroutine,Timer,Memory,Process,ProcessPool,Client,Event

server

创建一个异步服务器程序,支持TCP、UDP、UnixSocket 3种协议,支持IPv4和IPv6,支持SSL/TLS单向双向证书的隧道加密。使用者无需关注底层实现细节,仅需要设置网络事件的回调函数即可。 这个是官网的话,如果你按之前说的基础了解了,就应该知道这个server是做什么的,就是根据支持的协议进行接受请求,解包,发送,关闭请求,当然这些swoole已经封装到底层, 提供了几个函数接接口,你只用on注册事件,Connect,Receive,Close然后start,就可以写一个tcp服务,是不是很神奇?当然很多语言早就有了。。。,甚至人家从语言设计层面就支持异步,php还得靠swoole这种扩展..

HttpServer

用于开发一个http服务器,当然这是对Http协议支持的一个类。里面有我们属性的 request和response。request里面有header,server,get,post,cookies等。 response有返回状态 数据等。这些都是协议内的内容。 这个类通过

$http->on('request', function ($request, $response) {
    $response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});

处理请求和返回数据。这样就不用再通过nginx到php-fpm到php-cgi然后又返回。不过官方说对http协议支持不完整,还是应该用nginx做为代理。

我记得大学的时候刚接触web编程的时候是asp,八大对象,request,response,session,file等,http协议其实比较简单,从事web开发的朋友应该去看和了解下。

WebSocketServer

由于http协议是无状态的,每次要进行数据交互,都要完成请求,发送数据,返回,结束,3次握手确认下来,浪费大量时间,所以聪明的人设计了websocket, 只用完成一次握手,浏览器和服务器形成了一条高速通道,直接互相发送数据。 这个类就是对websockt支持协议,

$server->on('message',function(Swoole\WebSocket\Server $server, $frame){});

接受请求数据和返回

Coroutine协程

swoole的协程改了好几个版本了,swoole1-4协程改进了很多,现在已经可以通过同步的编程模式实现异步编程。 以前是无所不在的yield. 至于协程到底是啥,怎么用,参考:https://wiki.swoole.com/wiki/page/p-coroutine_realization.html。有兴趣的可以去研究他的底层实现代码。

这里对新手强调一点,协程用于处理异步耗时任务。就像前面说的,循环10万次请求接口。
大部分情况你不用去关心,因为swoole已经实现了SwooleCoroutine下面一系列的组件包括http,mysql,redis,socket等,当然你可以手动的用go(function(){})的方式手动去调用。
还有一点要注意, SwooleCoroutineClient并不是继承自Client,这2个不是继承关系,只是CoroutineClient大部分方法可以和Client用法一样。

process

这个是swoole的进程模块,涉及到高并发编程,就不得不谈到多进程,多线程的问题。多进程多线程又会带来进程间通信,父子进程通信和管理问题。这个模块就是用于处理这些问题。
SwooleProcess提供了如下特性

  • 基于Unix Socket和sysvmsg消息队列的进程间通信,只需调用write/read或者push/pop即可
  • 支持重定向标准输入和输出,在子进程内echo不会打印屏幕,而是写入管道,读键盘输入可以重定向为管道读取数据
  • 配合Event模块,创建的PHP子进程可以异步的事件驱动模式
  • 提供了exec接口,创建的进程可以执行其他程序,与原PHP父进程之间可以方便的通信

如果要成为高并发编程高手,就可以去深入了解下
目前我们只用按照官方文档,测试完他提供的接口即可编写出多进程高并发的程序。

这里有几个需要去了解的:
管道,这是个很重要的概念,进程间通信方式,这个需要在网上搜些文章来理解,否则进程间通信你会感觉很吃力
Reactor、Worker、TaskWorker的理解,和他们之间的关系 https://wiki.swoole.com/wiki/page/163.html

ProcessPool

进程池,基于Server的Manager模块实现.管理多个工作进程,该模块的核心功能为进程管理。它比上的Process实现多进程,更简单,更高层次的封装。看他提供的接口就知道了,on,listen,wirte,start,getProcess就够了。

Client

提供了TCP/UDP socket的客户端的封装代码,使用时仅需 new SwooleClient 即可。2种模式同步阻塞客户端,异步非阻塞客户端,区别和代码实例官网已经有了,就是用于请求服务接口。比如你一个请求进来了,你要去获取用户信息,产品,订单等,都是独立了服务,你就用Client去请求相应的接口,然后组合数据后返回到前端

Timer

这是个毫秒精度的定时器,类似与js里面的定时器。接口比较少,测试下demo应该很快能理解

Memory

主要用Table和Atomict

Table:
用于解决多进程/多线程数据共享和同步加锁问题,性能不用怀疑,单线程每秒可读写200万次,内置行锁自旋锁。你可以把他当成一个高速缓存来用。

Atomict:
底层提供的原子计数操作类,原子操作可以了解下。意思是一次只有一个操作。

比如在秒杀的时候,商品库存就2个,每个人请求进来,在多进程多线程的情况下,同时查询库存,而库存发生变化时,有可能会还是读出来是2。导致超卖。这个时候可以用Atomict,保证库存数量一直。当然如何实现的,有兴趣的可以去了解下自旋锁,你只要相信,你通过Atomict获取回来的库存是真实的库存即可。

可能你会问如果多台服务器呢?这个table是基于共享内存实现,多台服务器可以用zookeeper等实现分布式锁。

Event

除了异步Server和Client库之外,Swoole扩展还提供了直接操作底层epoll/kqueue事件循环的接口。可将其他扩展创建的socket,PHP代码中stream/socket扩展创建的socket等加入到Swoole的EventLoop中。 这是官方的说明

大致就是你可以通过Event直接去操作底层epoll/kqueue事件循环的接口,然后写一个满足自己业务的server和client出来


ok,至此我们对swoole有了个完整的认识。剩下的需要去属性各个模块和组件提供的接口和配置参数,假以时日,各位都是高并发编程的高手高高手,工资翻倍再翻倍

当然等你完全熟悉了swoole的开发,你可以再深入的了解下前面提到的底层知识和swoole的一些实现设计。

致一把年纪还在奋斗的自己!

标签: swoole

发表评论: