1.在 Server 程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web 服务器中发送邮件。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。

Swoole 提供了异步任务处理的功能,可以投递一个异步任务到 TaskWorker 进程池中执行,不影响当前请求的处理速度。(官网说明)

1. 服务端代码

执行服务端监听端口9501。通过设置daemonize这个参数,以守护进程在系统去维护这个TaskWorker进程池。我们客户端将消息传递给服务端,服务端异步将数据请求放入进程池队列运行,从大大缩短了响应时间。

<?php /**
* Created by PhpStorm
* User: pl
* Date: 2020/5/22
* Time: 15:23
*/ class TaskServer
{
private $server; public function __construct()
{
$this->server = new Swoole\Server('127.0.0.1', 9501);
$this->server->set([
'task_worker_num' => 3, //开启的进程数 一般为cup核数 1-4倍
'daemonize' => 1, //已守护进程执行该程序
'max_request' => 10000, //worker进程最大任务数
'dispatch_mode' => 2, //设置为争抢模式
'task_ipc_mode' => 3, //设置为消息队列模式
]);
$this->server->on('Receive', array($this, 'onReceive'));
$this->server->on('Task', array($this, 'onTask'));
$this->server->on('Finish', array($this, 'onFinish'));
$this->server->start();
} public function onReceive(swoole_server $server, $fd, $form_id, $data)
{
$this->server->task($data);
} /**
* @param swoole_server $server
* @param $fd
* @param $from_id
* @param $data
* 执行异步任务
*/
public function onTask($server, $fd, $from_id, $data)
{
$data = json_decode($data, true);
try { $log_txt = date('Y-m-d H:i:s') . "开始执行任务" . PHP_EOL;
$this->log($log_txt);
$type = $data['data']['type'];
$time = intval($data['data']['timing']);
unset($data['data']['timing']);
unset($data['data']['type']);
if (intval($type) == 1) {
$this->request_curl($data['url'], $data['data'], $data['data']['http_type']);
} else {
Swoole\Timer::after($time, function () use ($data) {
$this->request_curl($data['url'], $data['data'], $data['data']['http_type']);
});
}
} catch (\Exception $exception) {
$log_txt = date('Y-m-d H:i:s') . "执行任务失败发生错误" . PHP_EOL;
$this->log($log_txt);
}
} public function onFinish($server, $task_id, $data)
{
$log_txt = date('Y-m-d H:i:s') . "$data" . PHP_EOL;
$this->log($log_txt);
} public function request_curl($url = '', $request_data = '', $request_type = 'get', $headers = [], $is_ssl = false)
{
$ch = curl_init(); //curl初始化
if ($request_type == 'get' && !empty($request_data)) {
$num = 0;
foreach ($request_data as $key => $value) {
if ($num == 0) {
$url .= '?' . $key . '=' . $value;
} else {
$url .= '&' . $key . '=' . $value;
}
$num++;
}
$num = 0;
}
//区分get和post
curl_setopt($ch, CURLOPT_URL, $url); //URL地址
curl_setopt($ch, CURLOPT_HEADER, 0); //头信息不输出
//如果成功只将结果返回,不自动输出任何内容
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//post类型就实现此结果
if ($request_type == 'post') {
//设置为POST方式
curl_setopt($ch, CURLOPT_POST, 1);
//POST数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_data);
//当post数据大于1024时强制执行
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:"));
}
//判断是否绕过证书
if ($is_ssl) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//绕过ssl验证
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
if (!empty($headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch); //执行
if ($result == FALSE) return false;
curl_close($ch); //关闭资源
return $result;
}
public function log($log_txt)
{
$log = 'log/' . date('Y_m_d') . 'log';
if (!file_exists($log)) {
touch($log);
chown($log, 0777);
}
$file_log = fopen($log, "a");
fputs($file_log, $log_txt);
fclose($file_log);
}
} $task = new TaskServer();

2.客户端代码

<?php const API_KEY = 'xxx';

class ClientRequest
{
private $client;
private $params; //请求参数 public function __construct($params)
{
$this->client = new swoole_client(SWOOLE_SOCK_TCP | SWOOLE_KEEP);
$this->params = $params;
} public function connect()
{
if (!$this->client->connect('127.0.0.1', 9501, 1)) {
return json_encode([
'code' => 500,
'err_msg' => '链接异步客户端失败'
]);
}
/**
* 注意请求格式
* $params['url'] 接口地址
* $params['type']接口请求方式
* $params['data']参数
*/
$params = $this->params;
$array['url'] = $params['url'];
unset($params['url']);
$array['data'] = $params;
$this->client->send(json_encode($array, JSON_UNESCAPED_UNICODE));
}
} if($_SERVER['REQUEST_METHOD']!='POST') throw new ErrorException('路由不存在','404'); if(!array_key_exists('HTTP_TOKEN',$_SERVER)){
header('Content-type: application/json');
echo json_encode(['code'=>'200007','token is not empty']);exit();
}
if($_SERVER['HTTP_TOKEN']!= API_KEY ) {
header('Content-type: application/json');
echo json_encode(['code'=>'200007','error token']);exit();
} $params = $_POST; $client = new ClientRequest($params);
$client->connect();

开始执行服务端程序,php TaskServer.php我们以接口形式上去调用另外一个耗时接口.简单对比一下响应速度。



最后补充:基于swoole 一个简单的异步队列就完成了。可以将此队列封装成api队列接口,将它丢到task里面去慢慢执行吧~哈哈

<a name="introduction1"></a>

补充新增的一次定时器任务,支持毫秒级

3.定时任务和异步接口

说明:

1、在swoole 中 毫秒【如 1000 表示 1 秒,v4.2.10 以下版本最大不得超过 86400000【一天】】

2、后台定时器操作接口:操作方法如下

当操作时间在一天内 则直接执行定时器

3、大于一天时

系统执行一个定时crontab任务 ->

每隔12-24小时 运行一次 将数据库执行接口时间大于当前时间且不超过一天的数据数据执行该接口

关 于用户执行撤销则通过推送数据接口去判断该数据是否进行推送

4、当该需要给执行接口添加参数时 直接将参数放入接口

接口文档

ClientRequest.php

请求方法 post
参数
参数 是否必选 备注 限制 新增
token 密钥【header】xxxx
url 执行接口的地址
type 1、异步执行该接口 2、定时执行该接口
http_type get、post
timing 定时执行该接口的时间 单位【毫秒】

基于 swoole 下 异步队列和毫秒定时任务 API的更多相关文章

  1. .Net中的并行编程-7.基于BlockingCollection实现高性能异步队列

    三年前写过基于ConcurrentQueue的异步队列,今天在整理代码的时候发现当时另外一种实现方式-使用BlockingCollection实现,这种方式目前依然在实际项目中使用.关于Blockin ...

  2. 基于异步队列的生产者消费者C#并发设计

    继上文<<基于阻塞队列的生产者消费者C#并发设计>>的并发队列版本的并发设计,原文code是基于<<.Net中的并行编程-4.实现高性能异步队列>>修改 ...

  3. 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储。

    https://github.com/kcloze/swoole-jobs 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储.参考资料:swoole https:/ ...

  4. LaravelS - 基于Swoole加速Laravel/Lumen

    LaravelS LaravelS是一个胶水项目,用于快速集成Swoole到Laravel或Lumen,然后赋予它们更好的性能.更多可能性.Github 特性 内置Http/WebSocket服务器 ...

  5. swoft-个基于 Swoole 原生协程的PHP 微服务框架

    刚才百度了一下swoft框架,官网打不开了,仓库也暂停了.不由感慨.曾经和同事踩了许多坑使用此极其小众的框架完成微服务项目.使用它的唯一目的就是提高程序性能(底层使用了协程),为此大家都学习了很多新知 ...

  6. .Net中的并行编程-4.实现高性能异步队列

    上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...

  7. HQueue:基于HBase的消息队列

    HQueue:基于HBase的消息队列   凌柏   ​1. HQueue简介 HQueue是一淘搜索网页抓取离线系统团队基于HBase开发的一套分布式.持久化消息队列.它利用HTable存储消息数据 ...

  8. PHP实现基于Swoole简单的HTTP服务器

    引用Swoole官方定义: PHP语言的异步.并行.高性能网络通信框架,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,数据库连接池,AsyncTa ...

  9. C# Winform 基于Task的异步与延时执行

    一.Task的机制   Task位于命名空间System.Threading.Tasks中,是.NET 4.0加入的新模块,其实现机制大致类似于线程池ThreadPool,不过对于ThreadPool ...

  10. 基于SEDA的异步框架设计与实现

    基于SEDA的异步框架设计与实现 二.为什么使用SEDA 目前,面对并发环境,主流互联网服务器编程模型有两种:多线程模型以及事件驱动模型.但是这两个模型都不足以解决这个问题.我们来首先看一下这两种编程 ...

随机推荐

  1. H5 电商新势力崛起:ZKmall模板商城 H5 版本的高性能开发秘籍

    H5电商新势力的崛起中,ZKmall模板商城H5版本以其高性能和灵活性脱颖而出.以下是ZKmall模板商城H5版本的高性能开发秘籍,结合技术选型.架构优化与核心实践,为全场景电商应用提供高效解决方案: ...

  2. Service Reliability Management: A Comprehensive Overview

    Service Reliability Management: A Comprehensive Overview Service reliability management is a critica ...

  3. 可横竖控制的Text bg Control

    using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [RequireComponent(typeof(Co ...

  4. 基于注解创建bean对象和注入方式

    一.配置spring核心配置文件ApplicationContext.xml,添加扫描包 二.注解创建bean对象 三.注入方法

  5. 使用TypeScript开发微信小程序(云开发)-入门篇

    配置小程序云开发 TypeScript 环境 1. 检查本地 nodejs 环境 2. 安装 TypeScript npm install typescript --save-dev 3. 初始化/配 ...

  6. 备份一个迭代查找TreeViewItem的辅助函数

    private TreeViewItem FindTreeItem(TreeViewItem item, Func<TreeViewItem, bool> compare) { if (i ...

  7. C#基础——超级方便的ExpandoObject类别

    这东西是.NET Framework 4.5 的新东西..发现这个,大概就跟发现新大陆一样的兴奋,让我再次赞叹Anders Hejlsberg 之神.. 这边有MSDN : http://msdn.m ...

  8. 【代码】JS|前端密码,浪漫至死不渝,祝我生日快乐

    今天是特别的日子,我想把这篇存稿发出来. 一次缺席,次次缺席,便不再期待重逢. 也是时候,解开最后一个设计过的谜题. 学加密的同时,我恰好写前端比较多,也有朋友找我测试他们前端页面上的加密方案的安全性 ...

  9. C/C++双叹号!!运算符

    1.问题引入 在阅读https://github.com/amhndu/SimpleNES源代码中ppu.cpp中发现如下代码 m_bgPage = static_cast<CharacterP ...

  10. [虚拟化/云原生] Kubernetes 安装部署指南

    1 Kubernetes 安装部署指南 1.1 前置工作与注意事项 IP Role Hostname Remark 172.16.1.72 master 和 node k8s-master-1 资源有 ...