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+包体协议
通过与数据传输之后会在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();
});
同一个服务可以监听多个端口
持续更新此文章
包头就是根据数据内容的转化为二进制记录数据的长度 ↩︎
转载:https://blog.csdn.net/jerryvd/article/details/116212750