初学swoole

Posted mr.杰瑞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初学swoole相关的知识,希望对你有一定的参考价值。

swoole是啥? 首先是c写的 。大家都知道越接近底层效率越快。
基于事件的
onStart :启动后在主进程(master)的主线程回调此函数
function onStart(Swoole\\Server $server);
参数:Swoole\\Server $server

在此事件之前Server已经进行
1.启动创建完成Manager进程
2.启动创建完成Worker子进程
3.监听所有TCP/UDP/unixSocket端口,但未开始Accept连接和请求
4监听了定时器
接下来要执行:主Reactor开始接收事件,客户端可以connect到server

onStart回调中,仅允许echo打印log,修改进程名称,不得执行其他操作(不能调用server相关换书等)

onShutdown 结束事件

onWorkerStart 在worker进程/Task进程启动时发生,这里创建的对象可以在进程生命周期内使用

在这里插入图片描述

常用功能:
https-Server服务
如果用swoole加速框架,框架的条件必须是ioc类型(容器),因为swoole是常驻内存。
WebSocket-Server服务
一般用于im通信,任务队列处理之后结果反馈

<sricpt>
	var websocket = new WebSocket('ws://127.0.0.1:9502');
	websocket.onopen = function(evt){
	console.log("connect to server");
	};
	websocket.onclose = function(evt){
	console.log("disconnect");
	};
	websocket.onmessage = function(evt){
	console.log('retrieved data from server:'+evt.data);
	};

定时器

//每隔2s触发一次
swoole_timer_tick(2000,function($timer_id){
 echo 'tick';
});
//3秒后执行
swoole_timer_after(3000,function(){
	echo "after";
});

网络协议分层 :阻塞与非阻塞
同步阻塞: 相当于串行化执行,执行吃饭1s,执行睡觉2s。一共用时3s
异步-非阻塞:边看电视,边吃饭 (相当于两个任务没有关联)

网络协议分层
请求-》路由(交换机)-》校验(分五层)
抽象层(socket) server->client 进行通信
1.应用层 (解析具体应用的数据)
2.传输层(端口,tcp/udp)http协议是基于tcp协议,websocket协议是在tcp协议下衍生的
3.网络层(ip校验)
4.链接层(header信息 mac地址 00-b8-sr-12)
5.实体层(光缆,得到数据包)

进程和cpu的关系
进程相当于男人,cpu相当于女人,进程有好多,cpu只有一个。就是一个抢的过程,进程1抢到了,那后面的进程就要等待。同一个时刻只有一个进程在执行。
有父进程和子进程,先父进程,后子进程

swoole结构
master:老板
manager:经理
worker:打工
task:外包
在这里插入图片描述

长短连接

任何需要从服务器中获取数据都是需要建立连接的,并且建立与关闭连接均是会消耗资源

短连接:一次连接一次交互,简称一次性
长连接:一次连接多次交互,简称连绵不断

健康检查

长连接断开的情况
1.轮询机制 服务端定时请求客户端 (耗性能)
2.心跳机制 客户端对服务端发送 (一定时间间隔发心跳包 随机字符1字节的数据包)
swoole默认关闭心跳检测
heartbeat_check_interval => 60
表示每60s,遍历所有的连接,如果该连接在120s内(heartbeat_idle_time未设置时默认为interval的两倍),没有向服务器发送任何数据,此时连接将被强制关闭。若未配置,则不会启用心跳。

//每隔5s检测,客户端在10s内还没有给服务器发送信息的连接
$server->set([
	'heartbeat_check_interval'=>5,//检测所有的连接
	'heartbeat_idle_time'=>10//10秒还没有给我发消息
]);

用定时器

swoole_timer_tick(2000,function($timer_id) use ($client){
echo '123';
$client->send(1);
$client->recv();
})

TCP与UDP对比
tcp:面向连接的, 可靠的 ,基于字节流的 传输层通信协议
使用三次握手协议建立连接,四次挥手断开连接

面向连接意味着两个使用TCP的应用(一个客户端和一个服务器)在彼此交换数据包之前必须建立一个TCP连接
也就是说:tcp 一对一的
包正数据通信的完整性和可靠性,防止丢包

每一条tcp连接都有两个端点(马士兵教育 所说的四元组)
这种端点就叫套接字(socket)

udp:无连接的传输协议,面向事务的简单 不可靠的,信息传输服务,将网络数据流压缩成数据包的形式(面向报文)
可一对一 ,一对多,多对一,多对多
较好的实时性,工作效率比tcp高,适用于高速传输和实时性较高的通信或者广播通信

个人理解:
tcp发短信
udp打电话,听广播,唉广播是不是没声音了,唉信号不好,你再说一次
这两者安不安全,自己品

tcp连接三次握手

在这里插入图片描述
从上图可以想到一个问题,如果这种模式被坏人利用,那就是DDOS攻击了

TCP粘包是啥?
tcp在发送数据的时候因为存在数据缓存的关系,对于数据在发送的时候,短时间内,如果连续发送很多小的数据就会可能一次性一起发送,还有就是对于大的数据就会分开连续发送多次

个人理解:就是会有多发的现象。

在这里插入图片描述

数据发送时会进入缓存区,

拆包
一个完整的包可能会被TCP拆分成多个包进行发送

什么时候发生粘包,什么时候发生拆包?

  • 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;
  • 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
  • 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
  • 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS

粘包处理方案

  1. 特殊字符 :客户端与服务端约定特殊符号,对接收的数据进行分割处理
  2. 固定包头1+包体协议
    通过与数据传输之后会在tcp的数据包中携带上数据的长度,服务端可以根据这个长度,对于数据进行截取
    在这里插入图片描述
    int = 4字节
    1字节=8byte
    个人理解:包头相当于固定长度的一段数据。里面记录包体的数据长度
    swoole处理粘包方式(特殊字符)
    open_eof_check
array(
	'open_eof_check'=>true,//打开eof检测
	'package_eof'=>"\\r\\n"//设置EOF
)

swoole处理粘包方式(固定包头)

$server->set(array(
	'open_length_check'=>true,//开启
	'package_max_length'=>2*1024*1024,//最大包的长度  2m
	'package_length_type'=>'n',//校验类型
	'package_length_offset'=>0,//从哪个开始
	'package_body_offset'=>2,//下标2
	//注意校验类型 
	'daemonize'=>1,//守护进程
	//worker工作进程个数
	'worker_num'=>2
))

worker_num 设置启动的worker进程数 默认cpu核数
//cpu两倍的核数

linux内核与用户调度
用户空间:传递指令给内核空间,会有阻塞(感知不到)

内核空间:返回结果给用户空间

*在这里插入图片描述*

在这里插入图片描述

1.阻塞模型 一直在等待 用一次 之后就要再重新建立资源
2.非阻塞模型 不再等待,一会再请求 用一次 之后就要再重新建立资源
3.io多路复用模型 内核空间没变,但是可以一直接受新的任务 (会重复利用资源)
4.信号驱动io (比如银行叫号)
5.异步io (直接说到你了 来吧)
在这里插入图片描述
在这里插入图片描述
聊天案例

$connections (Server->getClientList)
可以foreach遍历服务器当前所有的连接

进程隔离
1.redis
怎么使用协程
在这里插入图片描述
在这里插入图片描述

Co\\run(function(){//开启协程环境
	$cli = new \\Swoole\\Coroutine\\Http\\Client("192.168.169.1",9500);
	$cli->upgrade('/');//升级成websocket服务
    $data=file_get_contents('任务地址');//这里可以换成其他方式,redis等都行
    $cli->push($data);//推送消息
    $data = $cli->recv();//接收结果
    $cli->close();
});

同一个服务可以监听多个端口


持续更新此文章


  1. 包头就是根据数据内容的转化为二进制记录数据的长度 ↩︎

以上是关于初学swoole的主要内容,如果未能解决你的问题,请参考以下文章

PHP必用代码片段

初学者 CodeIgniter 概念 - 可重用的视图代码,该去哪里? (帮手?)

Swoole源代码学习记录——ReactorThread模块

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

laravel 整合 swoole ,并简单 ab 测试对比性能以及在 PHPstorm 中利用debug调试配置swoole服务中的PHP代码

初学scala4——trait混入