利用Swoole同时更新多台服务器代码

一个小型网站的架构, 前面一台负载均衡, 后面几台web服务器. 更新代码成了难题, 一个一个FTP传不现实, 而且容易漏传,导致两个WEB服务器的代码都不一致.

一个简单的想法:

利用Websocket Server发送更新指令, Websocket Client 接收到更新指令, 运行git pull更新代码.

WebSocket Client有几个角色:

  • Solider: 接收命令, 不能发送命令
  • Commander: 发送命令

流程图:

clipboard.png

部分代码实现:

<?php 
//Server.php
require_once './Table.php';

use Swoole\WebSocket\Server as WebSocketServer;

class Server
{
    protected $server;

    protected $table;

    public function __construct($config)
    {
        $this->table = new Table();
        $this->server = new WebSocketServer($config['host'], $config['port']);
        $this->server->set($config['configuration']);
        $this->addEventListener();
    }

    public function addEventListener()
    {
        $this->server->on('open', Closure::fromCallable([$this, 'onOpen']));
        $this->server->on('message', Closure::fromCallable([$this, 'onMessage']));
        $this->server->on('close', Closure::fromCallable([$this, 'onClose']));
    }

    private function onOpen($server, $request)
    {
        if ($request->get['role'] == 'commander') {
            $this->table->commander = $request->fd;
        } else {
            $soliders = $this->table->soliders;

            $soliders[] = $request->fd;

            $this->table->soliders = $soliders;
        }
    }

    private function onMessage($server, $frame)
    {
        if ($frame->fd == $this->table->commander) {
            $command = $frame->data;

            foreach ($this->table->soliders as $solider) {
                $this->server->push($solider, $command);
            }
        } else {
            $this->server->push($frame->fd, "You don not have any right to send message");
        }
    }

    private function onClose($server, $fd)
    {
        $soliders = $this->table->soliders;

        if (in_array($fd, $soliders)) {
            unset($soliders[array_search($fd, $soliders)]);
        }
    }

    public function run()
    {
        $this->server->start();
    }
}

$server = new Server([
    'host' => '0.0.0.0',
    'port' => 8015,
    'configuration' => [
        'daemonize' => 1,
    ]
]);

$server->run();
<?php 
//Client.php
use Swoole\Http\Client as WebSocketClient;

class Client
{
    protected $protocol;

    protected $host;

    protected $port;

    protected $query;

    protected $client;

    protected $allow_events = ['onOpen', 'onMessage', 'onClose'];

    public function __construct($url)
    {
        list('scheme' => $this->protocol, 'host' => $this->host, 'port' => $this->port, 'query' => $this->query) = parse_url($url);

        if ($this->protocol == 'wss') {
            echo 'unsupport protocol';
        }

        $this->client = new WebSocketClient($this->host, $this->port);
    }

    public function start(Callable $callback)
    {
        $this->client->upgrade('/?' . $this->query, $callback);
    }

    public function __set($field, $value)
    {
        if (in_array($field, $this->allow_events) && is_callable($value)) {
            $this->client->on(strtolower(substr($field, 2)), $value);
        } else {
            echo 'Unsupport Event';
        }        
    }
}

<?php 
//Solider.php
require_once './Client.php';

function parseCommand($data)
{
    return json_decode($data, true);
}

function updateCommand()
{
    //you can do something here
    exec('git pull');
    // exec('composer update');
    // exec('npm install');
}

$ws = new Client('ws://192.168.1.142:8015?role=solider');

$ws->onMessage = function($client, $frame) {
    list('command' => $command, 'params' => $params) = parseCommand($frame->data);

    echo $command;

    switch ($command) {
        case 'update':
            updateCommand();
            break;
    }
};

$ws->onClose = function($client) {

};

$ws->start(function ($client) {
    
});

\Swoole\Process::daemon();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button class="btn btn-primary" onclick="update();">更新</button>

    <script type="text/javascript">
        function update()
        {
            var ws = new WebSocket("ws://192.168.1.142:8015?role=commander");
                
           ws.onopen = function()
           {
              // Web Socket 已连接上,使用 send() 方法发送数据
              ws.send(JSON.stringify({"command": "update", "params": {}}));
           };
            
           ws.onmessage = function (evt) 
           { 
              var received_msg = evt.data;
              alert(received_msg);
           };
            
           ws.onclose = function()
           { 
              // 关闭 websocket
              alert("连接已关闭..."); 
           };


        }
    </script>
</body>
</html>

完整代码:

https://gitee.com/shuizhuyu/P...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用PHP Swoole实现多进程发送微信模板消息的代码示例: ```php <?php // 引入swoole库 use Swoole\Process; // 模板消息内容 $template_data = array( 'touser' => 'openid', 'template_id' => 'template_id', 'data' => array( 'keyword1' => array( 'value' => 'value1', 'color' => '#173177' ), 'keyword2' => array( 'value' => 'value2', 'color' => '#173177' ), //... ) ); // 创建进程 $worker_num = 4; // 进程数量 $workers = array(); // 进程数组 for($i = 0; $i < $worker_num; $i++) { $process = new Process(function(Process $worker) use ($template_data) { // 引入微信SDK库 require_once 'path/to/wechat-sdk/autoload.php'; // 初始化微信公众号配置 $options = array( 'token' => 'your_token', 'appid' => 'your_appid', 'appsecret' => 'your_appsecret' ); // 实例化微信公众号对象 $wechat = new WeChat($options); // 发送模板消息 $wechat->sendTemplateMessage($template_data); }, false, false); $process->name('worker_'.$i); // 设置进程名 $process->start(); // 启动进程 $workers[] = $process; // 添加进程到数组 } // 等待子进程结束 foreach($workers as $worker) { $worker->wait(); } ``` 以上示例中,我们使用了Swoole库的Process类来创建多个进程,每个进程中实例化微信公众号对象并发送模板消息。通过这种方式,可以提高模板消息的发送效率,同时避免单个进程发送过程中出现阻塞导致其他请求的延迟。 需要注意的是,在使用Swoole的多进程功能时,需要特别关注进程间的通信和数据共享问题。在本示例中,我们没有涉及到这些问题,因为每个进程内部都是独立的。如果需要进行数据共享,可以考虑使用Swoole提供的相关组件,例如Table、Atomic等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值