Короткая шпаргалка по организации использования websocket на связке Workerman, Yii2 и NGINX. Без использования расширений Yii2 из репозитория composer.
Заметки по Workerman
Несколько вещей которые были для меня не очевидны.
- голый Workerman запускается из консоли, запустить его в web action Yii2 не получится. Т.е. сначала надо его запустить на сервере, а потом уже использовать во вьюхах.
- Workerman можно запустить с ключом -d чтобы демонезировать его
- мы запускаем Workerman в виде http сервера, а NGINX может проксировать любой трафик в том числе ws и wss
Все нижеописанное работает, но не очень красиво, я это понимаю ;)
Установка Workerman
Идем в папку с установленным Yii2 (где композер и папка вендор)
1 |
composer require workerman/workerman |
Настраиваем проксирование NGINX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; # SSL configuration listen 443 ssl http2; listen [::]:443 ssl http2; include snippets/self-signed.conf; include snippets/ssl-params.conf; server_name default.tld; root /home/web/default.tld; # всякое разное... # Для файлов отключить логирование, установить максимальный срок жизни кэша. location ~* ^.+\.(svg|svgz|eot|otf|woff|ttf|jpg|jpeg|gif|png|ico|zip|css|js)$ { access_log off; log_not_found off; expires 90d; } location = /ws { set $suffix ""; if ($uri = /index.php) { set $suffix ?$query_string; } proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # IF https proxy_set_header HTTPS "on"; proxy_pass http://127.0.0.1:9501$suffix; } location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; } location ~ /\.ht { deny all; } } |
Запускаем сервер Workerman
Для этого сделаем файлик в корне домена. Назовем его ws.php. Там что-то вроде.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php // Настройки консольного Yii2, практически полная копипаста // чтобы из функций иметь доступ ко всему функционалу инстанса Yii2 (модельки) $yii_dir = __DIR__.'/yii2base181005'; require($yii_dir . '/vendor/autoload.php'); require($yii_dir . '/vendor/yiisoft/yii2/Yii.php'); $config = require($yii_dir . '/config/console.php'); new yii\console\Application($config); // А тут запускаем сервер и вешаем универсальный обработчик use Workerman\Worker; $http_worker = new Worker("http://127.0.0.1:9501"); $http_worker->count = 4; $http_worker->onMessage = function($c, $data) { $data = json_decode($data, true); if(isset($data['method']) && method_exists('WorkermanController', $data['method'])) { $method = $data['method']; WorkermanController::$method($c, $data); } }; Worker::runAll(); // Можно обойтись и без класса, чисто функциями, но с классом привычнее class WorkermanController { public static function test($c, $data){ $time = time(); do{ $c->send((time() - $time)); sleep(1); }while( (time() - $time) < 90); $c->send("Finished\n"); } } |
Чтобы его запустить в консоли запускаем
1 |
php /home/web/default.tld/yii/yii2base181005/ws.php start -d |
Обращение к Workerman через Javascript websocket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<script> var socket = new WebSocket("wss://default.tld/ws"); document.getElementById("btn").onclick = function() { socket.send(JSON.stringify({ method: "test", data : "some data" })); }; socket.onmessage = function(event) { console.log(event); document.getElementById("got").innerText = event.data; }; </script> |
Anton 2019-09-02