异步发送邮件完整示例

异步发送邮件完整示例

大家好,又见面了,我是全栈君。

本章使用task异步进程进行邮件发送,来阐述一下以上章节提到的各个知识点。

邮件类

下载swiftmailer

composer require "swiftmailer/swiftmailer:^6.0"

Mailer.php 与 vender目录 同级

require_once __DIR__ . '/vendor/autoload.php';

class Mailer
{
    public $transport;
    public $mailer;
    /**
     * 发送邮件类 参数 $data 需要三个必填项 包括 邮件主题`$data['subject']`、接收邮件的人`$data['to']`和邮件内容 `$data['content']`
     * @param Array $data
     * @return bool $result 发送成功 or 失败
     */
    public function send($data)
    {
        $this->transport = (new Swift_SmtpTransport('smtp.qq.com', 25))
            ->setEncryption('tls')
            ->setUsername('bailangzhan@qq.com')
            ->setPassword('xxxxxx');
        $this->mailer = new Swift_Mailer($this->transport);

        $message = (new Swift_Message($data['subject']))
            ->setFrom(array('bailangzhan@qq.com' => '白狼栈'))
            ->setTo(array($data['to']))
            ->setBody($data['content']);
            
        $result = $this->mailer->send($message);

        // 释放
        $this->destroy();
        return $result;
    }
    public function destroy()
    {
        $this->transport = null;
        $this->mailer = null;
    }
}

Server

后端启动:php server.php
这里单独拆分了一个TaskRun类,并且在onWorkerStart之后进行载入,主要是为了之后的“平滑重启“

class TaskServer
{
    private $_serv;
    private $_run;

    public function __construct()
    {
        $this->_serv = new Swoole\Server("127.0.0.1", 9501);
        $this->_serv->set([
            'worker_num' => 2,
            'daemonize' => false,    //是否开启守护进程
            'log_file' => __DIR__ . '/server.log',    //守护进程调试日志
            'task_worker_num' => 2,
            'max_request' => 5000,    //防止内存泄漏
            'task_max_request' => 5000,    //防止内存泄漏
            'package_eof' => "\r\n", //设置EOF
            'open_eof_split' => true, // 自动分包
        ]);
        $this->_serv->on('Connect', [$this, 'onConnect']);
        $this->_serv->on('Receive', [$this, 'onReceive']);
        $this->_serv->on('WorkerStart', [$this, 'onWorkerStart']);
        $this->_serv->on('Task', [$this, 'onTask']);
        $this->_serv->on('Finish', [$this, 'onFinish']);
        $this->_serv->on('Close', [$this, 'onClose']);
    }
    public function onConnect($serv, $fd, $fromId)
    {
    }
    public function onWorkerStart($serv, $workerId)
    {
        require_once __DIR__ . "/TaskRun.php";
        $this->_run = new TaskRun;
    }
    public function onReceive($serv, $fd, $fromId, $data)
    {
        $data = $this->unpack($data);
        $this->_run->receive($serv, $fd, $fromId, $data);
        // 投递一个任务到task进程中
        if (!empty($data['event'])) {
            $serv->task(array_merge($data , ['fd' => $fd]));
        }
    }
    public function onTask($serv, $taskId, $fromId, $data)
    {
        $this->_run->task($serv, $taskId, $fromId, $data);
    }
    public function onFinish($serv, $taskId, $data)
    {
        $this->_run->finish($serv, $taskId, $data);
    }
    public function onClose($serv, $fd, $fromId)
    {
    }
    /**
    * 对数据包单独处理,数据包经过`json_decode`处理之后,只能是数组
    * @param $data
    * @return bool|mixed
    */
    public function unpack($data)
    {
        $data = str_replace("\r\n", '', $data);
        if (!$data) {
            return false;
        }
        $data = json_decode($data, true);
        if (!$data || !is_array($data)) {
            return false;
        }
        return $data;
    }
    public function start()
    {
        $this->_serv->start();
    }
}
$reload = new TaskServer;
$reload->start();

TaskRun 业务类

当此处修改了代码后,可以进行平滑重启,因为他是在Server端的onWorkerStart之后加载的文件。

require_once ('./Mailer.php');
class TaskRun
{
    public function receive($serv, $fd, $fromId, $data)
    {
    }
    public function task($serv, $taskId, $fromId, $data)
    {
        try {
            switch ($data['event']) {
                case 'send-mail':
                    $mailer = new Mailer;
                    $result = $mailer->send($data);
                    break;
                default:
                    break;
            }
            return $result;
        } catch (\Exception $e) {
            throw new \Exception('task exception :' . $e->getMessage());
        }
    }
    public function finish($serv, $taskId, $data)
    {
        return true;
    }
}

Client

client加了eof,为了防止粘包,通过网址访问该程序

$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);

$client->connect('127.0.0.1', 9501) || exit("connect failed. Error: {$client->errCode}\n");

$data = [
    'event' => 'send-mail',
    'to' => '5566***@qq.com',
    'subject' => 'just a test',
    'content' => 'This just a test.',
];

$client->send(togetherDataByEof($data));    //发送数据给服务端

$client->close();   //关闭连接

/**
 * 数据末尾拼接EOF标记
 * @param Array $data 要处理的数据
 * @return String json_encode($data) . EOF
 */
function togetherDataByEof($data)
{
    if (!is_array($data)) {
        return false;
    }
    return json_encode($data) . "\r\n";
}

异步发送邮件完整示例

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/111876.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • ComponentName的用法

    ComponentName的用法在android应用中打开别的应用我当时第一眼看到的时候是懵逼的,这是个什么玩意开启界面不都是startActivity(intent)的吗?后来才反应过来不是要起自己界面中的Activity

  • linux 重启服务器命令[通俗易懂]

    linux 重启服务器命令[通俗易懂]Linux有如下的关机和重启命令:shutdown,reboot,halt,poweroff,那么它们有什么区别呢?shutdown-建议使用的命令shutdown是最常用也是最安全的关机和重启命令,它会在关机之前调用fsck检查磁盘,其中-h和-r是最常用的参数:-h:停止系统服务并关机-r:停止系统服务后重启下面看几个例子:shutdown-h…

    2022年10月18日
  • 数据仓库ods层_app数据仓库搭建

    数据仓库ods层_app数据仓库搭建8.数据仓库之ODS层搭建

  • vue前端跨域解决方案有哪些_前端能完全解决跨域问题吗

    vue前端跨域解决方案有哪些_前端能完全解决跨域问题吗为什么会出现跨域:浏览器访问非同源的网址时,会被限制访问,出现跨域问题.常见的跨域有三种:jspn跨域,原理:动态生成script标签,通过script标签引入接口地址(因为script标签不存在跨域的)cors跨域(后端开启):全称“跨域资源共享”,原理:它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制vue代理服务器proxy跨域:通过请求本地的服务器,然后本地的服务器再去请求远程的服务器(后端部署接口的服务器),最后本地服务器再将请求

  • Cortex M3 NVIC与中断控制

    Cortex M3 NVIC与中断控制CortexM3 NVIC与中断控制宗旨:技术的学习是有限的,分享的精神的无限的。一、NVIC概览——嵌套中断向量表控制器    NVIC的寄存器以存储器映射的方式来访问,除了包含控制寄存器和中断处理的控制逻辑之外,NVIC还包含了MPU、SysTick定时器以及调试控制相关的寄存器。NVIC共支持1至240个外部中断输入(通常外

  • Python框架区别是什么?比较常用的框架有哪些?

    Python框架区别是什么?比较常用的框架有哪些?前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。众所周知,Python开发框架大大减少了开发者不必要的重复劳动,提高了项目开发效率的同时,还使得创建的程序更加稳定。目前比较主流的Python框架都有哪些呢?一般大家用的比较多的是Django、Flask、Scrapy、Diesel、Cubes、Pulsar和Tornado。那么这些Python框架的区别是什么呢?下面我们一起来看看这些Python框架的不同适用环境。.

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号