一个小型网站的架构, 前面一台负载均衡, 后面几台web服务器. 更新代码成了难题, 一个一个FTP传不现实, 而且容易漏传,导致两个WEB服务器的代码都不一致.
一个简单的想法:
利用Websocket Server发送更新指令, Websocket Client 接收到更新指令, 运行git pull
更新代码.
WebSocket Client有几个角色:
- Solider: 接收命令, 不能发送命令
- Commander: 发送命令
流程图:
部分代码实现:
<?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>
完整代码:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。