hayashier Tech Blogs
  • hayashier Tech Blogs
  • Author's Books
    • 実践Redis入門 (日本語版)
    • 実践Redis入門 (한국어판)
  • Top Contents
    • Dive Deep Redis
    • Dive Deep Memcached
    • Kubernetes 入門
    • TCP 入門
    • TLS 入門
    • GPG 入門
    • サービス障害が発生した場合の対応方法
    • よく使うトラブルシューティング コマンド実行例 まとめ
    • コピペで使えるELBのアクセスログ解析による事象分析 (ShellScript, Athena)
  • Containers
    • Docker 入門
    • Nomad 導入
    • Dockerを利用してさっと検証環境構築
  • Kubernetes
    • Kubernetes 入門
    • Kubernetes 導入 with Amazon Linux 2
    • EKSを利用してKubernetesでSpring MVCをデプロイ (NLB + Auto Scaling)
  • Load Balancer
    • ALB 認証 導入
    • TLS extensions support with ALB
    • ELB(CLB,ALB,NLB)の種類ごとのHTTPレスポンスの違い
    • ELB(CLB) で WebSocket 通信
  • RDBMS
    • PostgreSQL DBA 入門
    • RDBMS Benchmark Get Started
    • RDBMS サンプルデータ生成 Get Started
    • RDS PostgreSQL Extensions Get Started
    • RDBMS Engine Inspection for Troubleshooting
  • Redis
    • Dive Deep Redis ~ 入門から実装の確認まで
    • Dive Deep Redis Internals ~ GETコマンド実行時の動作 ~
    • RedisのString型は今でも本当に512MBが上限か?
    • Redis 公式ドキュメント まとめ
    • Redis / Memcached Source Code Reading - Overview -
  • Memcached
    • Dive Deep Memcached ~ 入門から実装の確認まで ~
    • Dive Deep Memcached ~ SETコマンド実行時の動作 ~
    • Memcached 公式ドキュメント まとめ
    • memtier_benchmark + memcached-tool の導入
    • Redis / Memcached Source Code Reading - Overview -
  • Hadoop
    • Hadoop Get Started
  • Networking
    • TCP 入門
    • TLS 入門
    • ksnctf: HTTPS is secure, Writeup (TLS 通信解読)
    • オンプレ側ルーター(Cisco 1812J, Juniper SRX210, YAMAHA RTX 1210)から Direct Connect へ BGP 設定
  • Software
    • アルゴリズムとデータ構造 入門
    • デザインパターン 入門
    • ソフトウェアテスト 入門
  • System Admin
    • Shell Script 入門
    • サービス障害が発生した場合の対応方法
    • よく使うトラブルシューティング コマンド実行例 まとめ
    • コピペで使えるELBのアクセスログ解析による事象分析 (ShellScript, Athena)
    • GPG 入門
    • Operation Misc
  • Development
    • ローカル環境のプログラミング言語のバージョンを切り替え macOS
    • /usr/local/Cellar/pyenv/1.2.21/libexec/pyenv: No such file or directoryのエラーの対処方法
  • AWS
    • AWS Misc
    • AWS CLI, AWS SDKのリトライ処理の実装について
    • AWS CLI バージョンアップでエラー発生を解消
    • Elastic Beanstalkで稼働しているアプリケーション(Ruby, Sinatra)をAmazon Linux AMIからAmazon Linux2へ移行
    • Elastic Beanstalkでインスタンス入れ替え後にnginxのデフォルトの画面が表示されてしまう問題の対応
    • Amazon Lightsail に SSL 証明書設置 with Let's Encrypt (自動更新)
    • Amazon Lightsailで10分で作るお手軽Markdownで書く独自ドメインのブログサイト構築
    • Lambdaをローカルでテスト(with Docker)
    • ECS + ALB でダウンタイムなしでデプロイ
    • `Repository packages-microsoft-com-prod is listed more than once in the configuration`のメッセージの解消方法
  • Others
    • Pandoc 導入
    • textlint + prh による文章校正
    • 紙書籍をPDFに変換
    • Sphinx 導入
    • さくっとPocketのブックマークをはてなブックマークに移行
    • Macが突然起動しなくなった話
    • Macでターミナルが開かない (zsh編)
    • ホスト型 IDS Tripwire とネットワーク型 IDS Snort の導入 with CentOS 6
    • JMeter 導入
    • Squid 導入 with Amazon Linux AMI
    • Spring MVCを導入 (+ MySQL, Redis)
    • 外資系企業で働いている場合の確定申告方法 (RSU考慮)
Powered by GitBook
On this page
  • ELB(CLB) で WebSocket 通信
  • 設定
  • プログラムの作成
  • ELBのProxy Protocolの設定
  • 動作確認
  • 参考
  1. Load Balancer

ELB(CLB) で WebSocket 通信

ELB(CLB) で WebSocket 通信

ALB では標準で WebSocket プロトコル機能に対応しているため、HTTP/HTTPS リスナーで受けて HTTP/1.1 から Upgrade で WebSocket 通信を開始することができます。 しかしながら、CLB, NLB では、ELB の機能としては対応しておりませんが、TCP リスナーを経由してバックエンドで WebSocket の機能に対応することで実現可能です。TCP レイヤーではスティッキーセッションのようなセッション維持機能を利用することができないので、nginx でプロキシし、その際、接続元の IP アドレスの情報は Proxy Protocol を利用する形で、WebSocket 通信を行います。 ALB では、Upgrade からそれに続く WebSocket 通信の間でスティッキーセッション機能を利用することもできますが、WebSocket が1つの TCP コネクションを利用するため、スティッキーセッション機能を利用することなく一つのバックエンドに割り振られます。 ただし、CLB ではアイドルタイムアウトもあり、60秒間アイドル状態が続くとコネクションが切断されてしまいます。そのため、サーバ側から定期的に Ping を定期的に行い、Pong の応答を得てコネクションを維持する方法があります。

設定

Node.js のインストール

$ sudo yum install -y gcc-c++ make openssl-devel
$ curl -sL https://rpm.nodesource.com/setup_8.x | sudo bash -
$ sudo yum install -y nodejs

インストールされていることの確認

$ node -v
v8.11.3

npm のインストール

$ curl -L http://npmjs.org/install.sh | sudo sh
$ vim ~/.npmrc
$ vim ~/.bashrc
$ source ~/.bashrc

.npmrc

root = ~/.npm/libraries
binroot = ~/.npm/bin
manroot = ~/.npm/man

.bashrc に以下を追記

export PATH=$HOME/.npm/bin:$PATH
export NODE_PATH=$HOME/.npm/libraries:$NODE_PATH
export MANPATH=$HOME/.npm/man:$MANPATH

インストールされていることを確認

$ npm -v
6.3.0

Socket.IO 等のインストール

$ npm install socket.io
$ npm install express

nginx のインストール

$ sudo rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ sudo yum install -y nginx
$ sudo service nginx start
$ sudo chkconfig nginx on

プログラムの作成

$ vim index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  socket.broadcast.emit('hi');
  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
    io.emit('chat message', msg);
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});
$ vim index.html
<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
        $(function () {
            var socket = io();
            $('form').submit(function(){
            socket.emit('chat message', $('#m').val());
            $('#m').val('');
             return false;
        });
      });
    </script>
  </body>
</html>
$ vim /etc/nginx/nginx.conf
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

:
:

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        listen 80 proxy_protocol;
        real_ip_header proxy_protocol;
        # listen       80 default_server;
        # listen       [::]:80 default_server;
        # server_name  localhost;
        # root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_http_version "1.1";
            proxy_pass http://localhost:3000/;
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header X-Forwarded-For $proxy_protocol_addr;
            proxy_set_header X-Forwarded-Host $http_host;
        }

ELBのProxy Protocolの設定

$ aws elb create-load-balancer-policy \
  --load-balancer-name WebSocketCLB \
  --policy-name EnableProxyProtocol \
  --policy-type-name ProxyProtocolPolicyType \
  --policy-attributes \
    AttributeName=ProxyProtocol,AttributeValue=true \
  --region us-west-2

$ aws elb set-load-balancer-policies-for-backend-server \
  --load-balancer-name WebSocketCLB \
  --instance-port 80 \
  --policy-names EnableProxyProtocol \
  --region us-west-2


$ aws elb describe-load-balancers \
  --load-balancer-name WebSocketCLB \
  --region us-west-2

動作確認

ELB の FQDN に対してブラウザからアクセス http://.us-west-2.elb.amazonaws.com/ Socket.IOのアプリケーション起動

$ node index.js
listening on *:3000
message: abc
message: def

参考

  • https://qiita.com/you21979@github/items/4c9c382b9536effc590d

  • http://d.hatena.ne.jp/lettas0726/20110406/1302041546

  • http://d.hatena.ne.jp/lettas0726/20110406

  • https://socket.io/get-started/chat

  • https://qiita.com/yamamaijp/items/84da15b81ec5c16ffdd0

  • https://debiancdn.wordpress.com/2012/03/03/elb-loadbalancer-websocket/

PreviousELB(CLB,ALB,NLB)の種類ごとのHTTPレスポンスの違いNextPostgreSQL DBA 入門

Last updated 1 month ago