昨天梦回jm,醒来之后看着窗外万里晴空,想大声喊一句:爷青回!

我想起之前使用gearman的岁月。不知不觉也过了快5年,想总结一篇关于gearman的技术文章算是一种对青春的祭奠,再不写的话更少有phper用过这个强大的分布式任务分发框架,毕竟这个时代已经属于swoole。

先讲一下Gearman,它是一款用C++编写的分布式任务分发框架,通过暴露API给使用方来完任务委托,在多台机器上负载均衡且并发地执行任务。特别是密集型计算,可以使用Gearman去异步地完成任务调度。

Gearman的结构分成三个角色:

Client: 客户端,可以是不同的编程语言,如php,java,python等.

Job Server: 任务服务器,负责分派任务,不负责业务逻辑。

worker: 执行任务的节点,可以是不同的编程语言实现,不一定和clent端的语言一样,如java,php, python等。

整个流程图如下图所示:

下一步开始安装gearman和相关扩展,这次我们还是使用php来作为编程语言。之前我写过一篇文章讲在服务器上安装gearman,这里只讲一下在macpro上如何安装gearman和php扩展。

比起linux上面的编译安装,mac上安装很简单,使用brew命令如下:

brew install gearman

# 为了让上一步安装的gearman能直接在终端调用,需要先创建下面这个目录
sudo mkdir /usr/local/sbin
# 让当前用户成为gearman安装目录下的sbin的所有者
sudo chown -R $(whoami) $(brew --prefix)/sbin # 把link指向刚才安装的gearman
brew link gearman
# 这一步很关键,让终端可以直接调用gearmand命令
ln -s /usr/local/opt/gearman/sbin/gearmand /usr/local/bin

先介绍一下背景:

假设我们有一个场景,很多商家通过我们的结算平台进行天结算,然后结算单需要复杂的计算,然后结算完成后异步地把计算结果以附件excel的方式发送给用户。假设有十万商家,每天订单有上万每户,那么这是比较大的数据量,且都是在某个时间段开放结算,有并发的压力。

这个时候用户(也就是商家)非常想快速完成结算并看到结果,对于处理过程的等待是非常低容忍度的,我们需要考虑可以利用多个worker异步去处理这些结算任务。

首先编写worker端的代码:

<?php

$worker = new GearmanWorker();
$worker->addServer('127.0.0.1', 4730); // 可以注册多个server,server可以在不同的机器上。
// 非阻塞方式运行
$worker->addOptions(GEARMAN_WORKER_NON_BLOCKING); $worker->addFunction("calculate", "calculatePayment"); $worker->addFunction('send', "sendEmail"); while($worker->work());
// 计算结算单
function calculatePayment($job) {
$data = json_decode($job->workload()); // 开始复杂的计算 todo return $data; } // 发送邮件
function sendEmail($job) {
// todo $data = $job->workload();
send_email_with_attachment($data->email, $data->content);
return true;
}

然后是编写客户端,命名为client.php,代码如下:

<?php

$client = new GearmanClient();

$client->addServer();
echo "start the calling";
$paymentList = [['order_id' => '110112', 'product_id' => [2323,4455,4455], 'pay_money' => '4423.00'], [['order_id' => '110113', 'product_id' => [223,45,67], 'pay_money' => '1400.00']]];
$data = $client->addTask('calculate', json_encode($paymentList));
// 后台方式运行,因为毕竟只是发邮件
$client->addTaskBackground("send", $data); echo "finish\r\n";

然后可以先把gearmand跑起来,也就是job server这一块,命令很简单:


但是因为有可能任务执行失败或者gearmand服务因为各种原因挂掉,所以建议结合mysql做持久化,也就是把执行情况记录到mysql中,一旦出现问题down掉,重新运行的时候可以根据mysql中的执行记录从失败的记录开始重跑。

为了做持久化,先创建用于持久化的数据库和表:


CREATE DATABASE gearman; CREATE TABLE `gearman_queue` (
`unique_key` varchar(64) NOT NULL,
`function_name` varchar(255) NOT NULL,
`priority` int(11) NOT NULL,
`data` longblob NOT NULL,
`when_to_run` int(11),
PRIMARY KEY (`unique_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

运行gearmand的时候可以使用到mysql方式作为持久化,命令如下所示:

gearmand -q mysql \
--mysql-host=127.0.0.1 \
--mysql-port=3306 \
--mysql-user=mine \
--mysql-password=xxxxx \
--mysql-db=gearman \
--mysql-table=gearman_queue

然后可以把worker运行起来,可以多开几个终端,例如跑三个worker,命令如下:

php /path/to/folder/worker.php

然后再执行client去触发任务:

php /path/to/folder/client.php

剩下就交给gearman去分发任务了,worker开始并发地高效处理任务啦!

当然我们也要考虑监控和管理job server,可以用shell去监听,也可以自己编写一个Gearman manager工具。这是后面可以聊的,到时候另开一篇文章吧。

除此之外,其他我们对于worker部分完全可以考虑使用一些异构语言,如java或者golang,PHP只做客户端使用,有人已经编写了grpc去实现了。

今年gearman的作者还在不断迭代,目前最新版本是1.1.19.1, 我收回之前的话,还是很多人在为这个框架付出,听说10年前左右雅虎已经大面积使用这个gearman框架来做新闻聚合了,当然jm也有用。

gearman=swoole+任务分发,老骥伏枥,志在千里罢了。

Gearman实战第一弹:异步处理结算单的更多相关文章

  1. jQuery.Form.js 异步提交表单使用总结

    jQuery.Form.js 是一个用于使用jQuery异步提交表单的插件,它使用方法简单,支持同步和异步两种方式提交. 第一步:引入jQuery与jQuery.Form.js <script ...

  2. typecho流程原理和插件机制浅析(第一弹)

    typecho流程原理和插件机制浅析(第一弹) 兜兜 393 2014年03月28日 发布 推荐 5 推荐 收藏 24 收藏,3.5k 浏览 虽然新版本0.9在多次跳票后终于发布了,在漫长的等待里始终 ...

  3. 用layui前端框架弹出form表单以及提交

    第一步:引用两个文件 第二步:点击删除按钮弹出提示框 /*删除开始*/ $(".del").click(function () { var id = $(this).attr(&q ...

  4. RMQ_第一弹_Sparse Table

    title: RMQ_第一弹_Sparse Table date: 2018-09-21 21:33:45 tags: acm RMQ ST dp 数据结构 算法 categories: ACM 概述 ...

  5. Spring实战第一部分总结

                                                         Spring实战第一部分总结 第一章 综述 1. DI依赖注入让相互协作的组件保持松散耦合,而 ...

  6. vue+uni-app商城实战 | 第一篇:【有来小店】微信小程序快速开发接入Spring Cloud OAuth2认证中心完成授权登录

    一. 前言 本篇通过实战来讲述如何使用uni-app快速进行商城微信小程序的开发以及小程序如何接入后台Spring Cloud微服务. 有来商城 youlai-mall 项目是一套全栈商城系统,技术栈 ...

  7. 关于『HTML5』第一弹

    关于『HTML5』:第一弹 建议缩放90%食用 祝各位国庆节快乐!!1 经过了「过时的 HTML」.「正当时的 Markdown」的双重洗礼后,我下定决心,好好学习HTML5  这回不过时了吧(其实和 ...

  8. react实战系列 —— React 中的表单和路由的原理

    其他章节请看: react实战 系列 React 中的表单和路由的原理 React 中的表单是否简单好用,受控组件和非受控是指什么? React 中的路由原理是什么,如何更好的理解 React 应用的 ...

  9. Office宏病毒学习第一弹--恶意的Excel 4.0宏

    Office宏病毒学习第一弹--恶意的Excel 4.0宏 前言 参考:https://outflank.nl/blog/2018/10/06/old-school-evil-excel-4-0-ma ...

随机推荐

  1. python小白入门基础(二:变量)

    #变量:可以改变的量就是变量,实际上是由内存开辟的一块空间,临时存在内存中,以便后续代码使用.#作用:代指内存中某个地址中的内容. #1.变量的概念name = "王五"name ...

  2. MyBatis动态SQL(使用)整理

    MyBatis 令人喜欢的一大特性就是动态 SQL.在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的.MyBatis 动态 SQL 的出现, 解决了这个麻烦. MyBa ...

  3. Git 实用操作:撤销 Commit 提交

    有的时候,改完代码提交 commit 后发现写得实在太烂了,连自己的都看不下去,与其修改它还不如丢弃重写.怎么操作呢? 使用 reset 撤销 如果是最近提交的 commit 要丢弃重写可以用 res ...

  4. 来讲讲你对ThreadLocal的理解

    前言 面试的时候被问到ThreadLocal的相关知识,没有回答好(奶奶的,现在感觉问啥都能被问倒),所以我决定先解决这几次面试中都遇到的高频问题,把这几个硬骨头都能理解的透彻的说出来了,感觉最起码不 ...

  5. PHP 类的构造方法 __construct()

    1. 构造方法简介 构造方法 __construct() 是一种类结构特有的特殊方法,该方法由系统规定好 实例化一个类时:先调用该方法,再返回类的对象 构造方法也是普通方法,不同之处就是在实例化类时会 ...

  6. 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...

  7. selenium中Xpath标签定位和cssSelectors定位(优先用cssSelectors)

    二者的区别:xpath 支持角标定位,cssselector不支持 1.XPath是XML的路径语言,通俗一点讲就是通过元素的路径来查找到这个标签元素. xpath支持属性定位,无论是默认属性还是自定 ...

  8. [程序员代码面试指南]字符串问题-字符串匹配问题(DP)

    问题描述 字符串str,模式串exp. 必须保证str中无'.'和'星号'字符,并且exp中'星号'不出现在首位,且无连续两个'星号'.PS星号是字符只是暂时没找到markdown的星号转义字符. ' ...

  9. windows下nginx的配置

    这里做的nginx的配置主要的功能是: 能够用localhost访问本地文件夹中的项目 输入ip地址访问本地文件夹中的项目 反向代理其他地址访问本地文件 1.nginx安装地址 2.解压之后的文件如下 ...

  10. sql分页存储过程,带求和、排序

    创建存储过程: CREATE PROCEDURE [dbo].[sp_TBTest_Query] ( @PageSize INT, --每页多少条记录 @PageIndex INT = 1, --指定 ...