Press "Enter" to skip to content

Swoole入门实战打造高性能赛事直播平台

课程导学

1.异步特性
2.C语言编写的扩展
3.支持协程
4.异步,并行,高性能网络通信引擎

Swoole简介

PHP异步网络通信引擎
最终编译为so文件作为PHP的扩展

学习Swoole的准备工作

  • 有PHP基础,没swoole经验的小伙伴
  • linux环境下开发
  • php7 swoole2.1 redis
  • 源码安装php7 源码安装swoole

如何学习swoole

  • 查看文档
  • 实现swoole特性的功能点
  • 多看看其他现有的swoole案例代码

获取PHP7源码

wget https://www.php.net/distributions/php-7.4.2.tar.bz2

PHP7源码安装

tar -xjvf 解压

./configure –prefix=/home/work/study/soft/php

make make install

简化PHP执行命令

vim ~/.bash_profile

alias php=/home/work/study/soft/php/bin/php

source ~/.bash_profile

源码安装踩到的那些坑

拷贝php.ini文件

在源码目录拷贝php.ini-development到/home/work/study/soft/php/etc

mv php.ini /home/work/study/soft/php/lib/

php -i | grep php.ini

Swoole下载

官网下载 www.swoole.com

码云下载 https://gitee.com/swoole/swoole.git

Swoole源码安装

使用phpize生成config编译文件

./configure –with-php-config=/home/work/study/soft/php/bin/php-config

make && make install

远程连接Vargant服务器

https://blog.csdn.net/github_38097011/article/details/83688607

双剑合璧-PHP7支持Swoole

重启终端后php命令将不生效需要重新配置

需要修改php.ini文件使swoole扩展生效

Swoole-TCP服务器

使用vscode连接服务器编写代码即可

set函数用于设置初始参数如最大进程数或最大请求数

有4种写法:匿名函数,类静态方法,函数,对象方法

Swoole-TCP客户端

获取进程数: ps aft | grep tcp.php
查看进程: netstat -anp | grep 端口号

swoole是基于php cli的

创建client服务 new swoole_client(SWOOLE_SOCK_TCP)
连接 $client->connect();
fwite(STDOUT,”请输入消息”); 在命令行输入
fgets(STDOUT); 获取输入
使用send发送到服务器
使用recv获取服务器返回

问题:如何在不结束进程的情况下修改php文件

Swoole-UDP服务

TCP传输数据可靠,UDP速度快

异步传输

自行完成UDP

客户端无需连接直接向服务端发送即可

sendto 向客户端发送数据

使用nc做连接测试

    nc -u 127.0.0.1 9502

SwooleHTTP服务

HttpServer基于swoole_server

0.0.0.0 表示监听所有地址

获取数据  $request->get

输出数据 end方法,参数必须为字符串

设置cookie cookie,header

优先加载静态文件 enable_static_handler

WebSocket服务基本概述

  • 什么是websocket websocket是基于TCP的一种新的网络协议,它实现了浏览器与服务器全双工通信-允许服务器主动发送信息给客户端
  • 为什么需要websocket 缺陷:HTTP的通信只能由客户端发起
  • websocket特点 建立在TCP协议之上
    性能开销小通信高效
    客户端可以与任意服务器通信
    协议标识符ws wss
    持久化网络通信协议

websocket服务案例实现

open 连接打开事件

message 必须,消息事件

push 发送请求

写js

    js中websocket有各种事件可用于监听

1.创建一个服务 new Swoole\WebSocket\Server
2.创建监听事件 on:open,message,close
3.通过js的websocket的对象去执行响应请求

WebSocket服务优化

封装成类,方法拆分,用常亮保存参数
面向对象的可读性更强

HTTP服务可以建立长连接

Swoole Task任务使用

  • 使用场景 执行耗时的操作(发送邮件,广播等)
  • 如何使用 onTask,onFinish,设置task_worker_num

task是异步的,不需要等待

步骤:在onMessage方法中执行task方法传入对应参数,task方法中执行finish方法,finish方法时执行完毕后调用的,可以发送信息到客户端,在这之前需要先设置task_worker_num参数

Swoole毫秒定时器

  • 常规定时器 crontab
  • swoole定时器 Swoole\Timer::tick
    Swoole\Timer::after

定时器是异步的,有别名

该章节在最新swoole中被废弃

异步文件IO系统-读取文件

swoole_async_readfile 会异步执行,提高效率

异步文件IO系统-写文件

swoole_async_writefile FILE_APPEND追加操作

异步Mysql详解

常规sql查询,适用于更新并读取操作

    比如读取文章并进行阅读数的新增可以通过异步的方式

异步Redis – redis服务安装

官网下载redis 下载解压 tar -zxvf redis make

src 目录开启redis ./redis-server 客户端连接

异步Redis hiredis安装以及Swoole重新编译

hiredis安装 https://wiki.swoole.com/wiki/page/p-redis.html

swoole重新编译  ./configure --with-php-config=/home/work/study/soft/php/bin/php-config --enable-async-redis

测试 php --ri swoole

新版已被废除废除,安装redis扩展即可

异步Redis详解

swoole_redis 已被废除

进程详解

  • 什么是进程 进程就是正在运行的程序一个实例
  • php自带进程问题 不支持进程通信

1.引入Process Swoole\Process
2.Process创建构造函数
3.$process->start()启动,返回进程ID
4.exec方法可以执行外部程序
5.wait回收运行的子进程
6.ps aux | grep process.php查看当前进程
7.pstree -p id 查看进程树
8.ps aft | grep http_server

Swoole进程案例剖析

执行多个URL响应时间长,按需开启N个子进程执行

子进程会同时执行

进程间通讯可以使用通道

Swoole内存详解

  • 介绍 swoole_table 是一个基于共享内存和锁实现的超高性能,并发数据结构,用于进程之间的数据共享
  • 使用 1.new Swoole\Table()
    2.$table->coulmn 设置列
    3.$table->set 设置
    4.$table->create 生成
    5.$table->get 获取
    6.$table->incr 使值增加
    7.$table->decr 使值减少
    8.$table->exist 判断值是否存在

Swoole协程精讲

特点是可以通过过同步代码编写方式达到异步IO的效果和性能,避免了传统异步回调带来的逻辑代码混乱问题

效率会提高很多,代码是同时执行的

实战环境部署准备

框架选择 tp6
swoole特性使用
赛事直播平台
nginx 负载均衡
redis
系统监控和性能优化
  • 准备 下载tp6,导入静态文件,开启swoole http server

登录流程介绍

手机号,短信验证码,登录

让Swoole完美支持TP5

在http中运行tp的入口文件中的程序,需要使用onWorkerStart

热加载,提高性能

由于swoole中的参数获取和tp不同,需要在onRequest方法中执行对应方法获取server,header,get,post的参数

最后的输出需要用到缓冲区ob_start ob_get_contents ob_end_clean

会遇到超全局变量在刷新后还存在的问题,需要unset掉

define保存的数据不会被清空需要使用$server->close [该方法未找到]

上次的资源不会被清空需要使用$server->close();如果报错他不会中止而是重新启动一个进程,是存在问题的

最后优化处理

    将Request中的pathinfo方法和path方法不需要的代码删除,使用?s方式访问即可

阿里大于以及SDK获取

SDK下载

需要安装composer,需要安装openssl

基于阿里短信服务发送第一个短信验证码

下载PHPSDK后放入extend文件夹中,创建common\lib\ali\Sms文件,将demo放入

手机号码登录 – 获取验证码

增加Send控制器,获取参数,生成验证码

一般下划线为字段规范

编写公共返回方法Util

swoole无法容忍exit需要return在内部函数中使用echo

使用redis保存code,设置过期时间,需要安装redis扩展

登录实现

输入手机号存在bug,使用原生获取方式或者修改

不建议使用文件存验证码如果是分布式的话会存在获取不到验证码的问题,使用异步redis方式解决

$.get的第四个参数写json可以直接将数据转换

不需要每次使用redis都要连接要创建Redis.php文件增加单例模式作为连接使用

进行手机号和验证码的校验之后将用户的信息也保存在redis或mysql中,明文不安全,可以使用post或者将code设为唯一,登录成功之后存入cookie用于判断用户是否登录

将redis设为后台运行https://blog.csdn.net/a909301740/article/details/81159543

vscode免密登录
https://blog.csdn.net/qq_34846662/article/details/99051947

登录模块优化

封装HTTP

不要相信第三方接口可以正常运作,如果对方服务器挂掉影响用户体验,使用task任务

封装Task

赛事直播介绍

赛况列表页,需要创建对应的赛事表

赛事直播业务分析

球队,人员,比分,直播员,互联网用户

赛事直播表的设计

  • 球队表 live_team id,name,image,type,create_time,update_time
  • 直播表 live_game id,a_id,b_id,a_score,b_score,narrator,image,start_time,status,create_time,update_time
  • 赛事赛况表 live_outs id,game_id,team_id,content,image,type,status,create_time
  • 球员表 live_player id,name,image,age,positition,status,create_time,update_time
  • 聊天表 live_chart id,game_id,user_id,content,status,create_time mysql的安装:https://blog.csdn.net/qq_37598011/article/details/93489404

Websocket服务搭建并支持http服务

将Http服务替换为WebSocket服务

赛事直播解说员页面搭建

直播数据入库,发送到页面

将直播员的页面放入,记得修改document_root

可以基于x-admin做后台管理系统

赛事直播员图片发布 – 上传图片

新增控制器,foreach $_FILES变量赋值 move() 移动文件

getSaveName() 获取图片名称返回即可

返回后将数据增加到input框中

赛事直播数据流程测试

将数据通过Post方法传递到后台,保存到数据库之后使用push方法将他展示在页面上

赛事直播在线用户处理

在open方法中将fd写入redis中,使用sadd方法

smembers key 取出

在close方法中将fd删除,使用srem方法

push的时候将redis中的值取出并遍历即可

赛事直播在线用户处理

针对两个参数的redis封装方法做优化

使用call方法调用不存在的方法

赛事直播逻辑开发

将后台数据转换为json格式发送到前端,前端再转为数组,使用prepend将数据渲染

赛事直播功能开发 – 优化

原理:用户连接websocket时,redis记录fd,后台增加数据时按照顺序push到对应用户的页面上

作业:比分增加

优化:使用task封装代码

聊天模块功能分析

轮询消耗资源,使用websocket更好

聊天室模块发送数据交互处理

回车事件,将数据发送到服务器
使用post将数据发送

聊天室chartjs文件编写

发送要换一个端口,否则数据会有冲突

Swoole中connections的使用场景

使用listen监听另一个端口,将live.js中的代码粘贴到chart中

遍历http_server对象中的ports数组中的connections属性

聊天室功能开发

将数据发送到客户端,将数据遍历

赛事直播也可以使用connections中的数据

系统监控与性能优化模块

监控为服务保驾护航

使用linux+swoole+php做监控

针对不同场景优化

服务监控

监控服务可以使用定时任务crontab,但是crontab最小粒度是一分钟,可以使用swoole定时器

通过netstat -anp | grep 8811方式监听

通过shell_exec方法执行脚本

命令应该为netstat -anp 2>/dev/null | grep 8811 | grep LISTEN | wc -l

判断返回的值做报警处理,比如发送邮件短信或记录日志:调用类库时需要引入tp框架的入口文件的内容

使用swoole定时器运行脚本

nohup 后台运行并将输出内容放入日志中,php需要是绝对路径

可以结合linux做各种监控,硬盘,内存,CPU等

nohup /usr/local/php/bin/php /home/wwwroot/swoole/script/monitor/Server.php  > /home/wwwroot/swoole/script/monitor/a.txt &

日志落盘处理

可以监控接口的响应时间,CPU的占用等,举一反三

writeLog记录$_POST,$_GET,$_SERVER数据,通过异步方式记录

多个请求过滤

写入文件后,使用agent挖掘日志,传到spark进行格式解析和计算之后存入数据库:elasticsearch

去除favicon.ico请求,判断request->server['request_uri']

服务平滑重启

当服务代码进行更改时进行平滑重启

sigusr1用于重启worker进程

给主进程一个别名,写shell脚本

echo 'loding...'
pid=`pidof live_master`
echo $pid
kill -USR1 $pid
echo 'loading success'

swoole也自带了reload方法重启

负载均衡概述

静态资源适合放在nginx中,减少静态资源的加载时间,设置缓存时间

用户访问nginx,如果有静态资源有先加载,然后转发到swoole

负载均衡nginx安装

官网下载nginx,解压

./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/usr/local/nginx/config/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --pid-path=/usr/local/nginx/logs/nginx.pid --http-log-path=/usr/local/nginx/logs/access.log

make -j make make install

负载均衡-静态文件支持

配置nginx配置

Nginx负载-nginx转发到Swoole服务器

编写规则
if(!-e $request_filename){
    proxy_pass http://127.0.0.1:8811;
}

负载均衡

upstrem swoole_http{
    server 127.0.0.1 weight = 2;
}

负载均衡就是配置多个服务器,根据权重访问不同的服务器,nginx转发消耗CPU

结束语

  • PHP Nginx Swoole安装
  • swoole基础知识
  • 图文直播案例
  • 系统监控,性能优化

结束:自己照着视频代码敲了一遍,遇到了很多关于linux的问题,坑还是比较多的,但是也很有用,关于nginx的性能优化还是需要以后多看,swoole挺好玩的,websocket是重点,定时任务和linux shell脚本也不错,遇到坑不要害怕,当性能要求高的时候用第三方框架也不一定是好事