Как развернуть socket.io в Google App Engine?

Я создал свое первое приложение node.js, используя socket.io. В частности, я применил пример чата, опубликованный socket.io. Он работает отлично, локально. И затем я попробовал развернуть его в Google App Engine (чтобы некоторые улучшения кода для node работали).

Все показывает, что часть node работает хорошо. Однако чат не работает, указывая, что часть socket.io не работает. Вы можете увидеть развернутое приложение (и источник страницы) здесь.

Должен ли я сделать что-нибудь еще? Что-то в файлах yaml или json?

yaml content:

runtime: nodejs
vm: true

skip_files:
  - ^(.*/)?.*/node_modules/.*$

Содержание json:

{
  "name": "Chaty",
  "description": "chatrooms app",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "McChatface",
  "engines": {
    "node": "~4.2"
  },
  "scripts": {
    "start": "node app.js",
    "monitor": "nodemon app.js",
    "deploy": "gcloud preview app deploy"
  },
  "dependencies": {
    "express": "^4.13.4",
    "socket.io": "^1.4.6"
  }
}

Ответ 1

Короче говоря, это не может быть сделано на производстве, и это, кажется, работа в процессе. Правильная архитектура - иметь чат-сервер на Google Compute Engine, как описано здесь.

Но в качестве доказательства концепции использовать socket.io в google app engine очень похоже на то, что показано в примерах google appengine для веб-сокетов.

В случае с socket.io выполните следующие действия на стороне сервера. Фрагмент кода ниже.

  1. Создайте второе экспресс-связующее ПО и сервер.
  2. Присоедините/используйте socket.io с новым сервером.
  3. Слушайте порт (65080).
  4. Откройте брандмауэр для порта (65080) на Google Compute Engine.
  5. Ссылка на рабочий репозиторий.

socket.io меняется на стороне сервера

    var app_chat = require('express')();
    var server1 = require('http').Server(app_chat);
    var io = require('socket.io')(server1);
    server1.listen(65080);

    io.on('connection', function (socket) {
      console.log('user connected');
      socket.on('chat_message', function (data) {
        console.log('client sent:',data);
        socket.emit('chat_message', 'Server is echoing your message: ' + data);
      });
    });

открыть брандмауэр по команде

gcloud compute firewall-rules create default-allow-websockets \
    --allow tcp:65080 \
    --target-tags websocket \
    --description "Allow websocket traffic on port 65080"

Я надеюсь, что Google вскоре предложит готовое к использованию решение, так как оно станет ключевой защитой в любом PaaS-арсенале.

Ответ 2

В Google есть пример приложения с использованием WebSockets здесь, вам нужно сделать следующее, чтобы заставить его работать правильно:

  • Откройте порт брандмауэра для сервера, чтобы клиенты могли дойти до вашего сервера.
  • Извлеките свой внутренний IP-адрес в Google App Engine, чтобы клиенты знали, какой IP-адрес для подключения к
  • Извлеките свой IP-адрес с вашего сервера через что-то вроде API-интерфейса для отдыха или HTML-страницы.

Это должно быть (не верьте мне на слово, это то, что я смог узнать после некоторых исследований в документах), надеюсь, что это поможет!

Получение внешнего IP-адреса из Google App Engine

var METADATA_NETWORK_INTERFACE_URL = 'http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip';

function getExternalIp (cb) {
    var options = {
        url: METADATA_NETWORK_INTERFACE_URL,
        headers: {
            'Metadata-Flavor': 'Google'
        }
    };

    request(options, function (err, resp, body) {
        if (err || resp.statusCode !== 200) {
            console.log('Error while talking to metadata server, assuming localhost');
            return cb('localhost');
        }

        return cb(body);
    });
}

Открытие порта брандмауэра

gcloud compute firewall-rules create default-allow-websockets \
    --allow tcp:65080 \
    --target-tags websocket \
    --description "Allow websocket traffic on port 65080"

Ответ 3

Поддержка GAE для постоянных сокетных соединений появилась в феврале 2019 года !

Чтобы это работало, вам нужно использовать flex среду и изменить свой app.yaml включив в него session_affinity:

network:
  session_affinity: true

Обратите внимание, что мне все еще пришлось открыть порт 65080, чтобы это работало, но никаких других изменений для меня не требовалось.

Читайте Deets по адресу:

https://cloud.google.com/appengine/docs/flexible/nodejs/using-websockets-and-session-affinity