戻る

NginxとGoのWebSocketの連携

Webサーバーの環境構築は十人十色なところもあるため慣れていないと難しい. 今回GoアプリケーションをNginxから呼び出すための環境構築について説明する.

Nginxの設定

/etc/nginx/nginx.confの一部を次のように編集する. fastcgi_passでローカルの適当なポートを通してGoアプリケーションに接続する. 今回9000としたが, 空いてそうなポートならなんでも良い. 余力がある人は, proxy_passをtcpポートではなくunixドメインソケットでする方法も調べてみよう. そちらの方が推奨されていると思う. さて, WebSocketを使うにはヘッダーにUpgradeをセットすることでWebSocketを使うことを明示する必要がある.


    location /chat {
      proxy_pass http://localhost:9000;
      proxy_set_header Host $host;
    }
    location /chat/wss {
      proxy_pass http://localhost:9000;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header Host $host;
    }

もちろんnginx.conf編集後は再起動を忘れない


systemctl restart nginx

Goの環境構築

今回/usr/local/gocode/をGOPATHとしてアプリケーションを配置しする.次のように配置している. binに実行ファイル, src/ドメイン名/パッケージ名/にソースコードをいれる. chatディレクトリにはgorilla/websocketのchat exampleを入れる.


/usr/local
├── gocode
│   ├── bin
│   │   └── chat
│   └── src
│       └── hogehoge.com
│           └── chat
│               └── main.goなど

さて, /usr/localは通常rootユーザーが所有権を持っており, そこで作成したファイルもその所有権が引き継がれる. gocodeディレクトリを作成した後, 次のコマンドで所有権を変更する. goのソースコードを実際に編集するのはログインユーザーで行いたいのでそれを指定し, グループはWebサーバーの実行ユーザーのグループを指定すると良いだろう. w権限をWebサーバーにも与えたい時はよくあり, ログインユーザーにも与えたいのでグループにw権限を付与するということが多い. 私の場合ログインユーザー(zaief)をhttpグループにも入れている.


chown -R zaief:http gocode

GOPATH, PATHを設定する. PATHの設定は今回絶対パスでgoアプリケーションを実行するためいらないが, ログインユーザーで何か呼び出したい時もあるかもしれないので設定する. GOPATHはgo install時などにインストール先を指定するため必要. ログインユーザーのシェルの設定ファイルに書き込む. 私の場合zshを使っているため~/.zshrcを次のように編集した.


export PATH=$PATH:/usr/local/gocode/bin/
export GOPATH=/usr/local/gocode/

Goアプリケーションを作成

main.goには次のように記述した. Nginxがローカルホスト127.0.0.1:9000でアクセスしてくるのでnet.Listen()で応答させるよう設定する. とても簡単な応答をするアプリだ.

websocketの例はどうしても煩雑になってしまうので, gorilla/websocket/のchatのexampleをchatディレクトリにそのまま移す.



移したら, go install でGOPATHで指定したディレクトリ/bin/ にビルドしたバイナリが配置される. chatという名前のバイナリができている. go installを実行した場所のディレクトリ名が使われることに注意しよう. 特に, mainという名前のバイナリが作成されるわけではない.


go install

$GOPATH/bin/chat で実行してみよう. nginxで定めたurlからアクセスできるはずだ.

アプリケーションの自動起動

さて, 先ほど実行したのはログインユーザーなのでログアウトしてしまうとアプリケーションのプロセスは終了してしまう. そこでwebサーバーの実行ユーザーなどにこれを任せてしまいたい. そのためにはsystemdにデーモンを登録する必要がある. 次のようなファイルを作成し, /etc/systemd/system/goserver.serviceとして保存しよう. User = httpが特に重要で, rootユーザー以外のものを選択するのが良い.


[Unit]
Description = hogehoge.com

[Service]
ExecStart = /usr/local/gocode/bin/chat
ExecStop = /bin/kill -SIGTERM $MAINPID
ExecReload = /bin/kill -SIGTERM $MAINPID && /usr/local/gocode/bin/chat
Restart = always
User = http
Type = simple

[Install]
WantedBy = multi-user.target

作成したら, systemdに登録する.


systemctl daemon-reload
systemctl enable goserver
systemctl start goserver

これでデーモンとしてアプリケーションを常駐させることができた. これで一通り流れがわかっただろう. nginxを使わずgo単体でwebサーバーとして機能させる解説が多いが今回nginxと連携ができより実用性のあるものとなっている.