Symfoware

Symfowareについての考察blog

Ubuntu 18.04 + nginx + lua拡張モジュールでRedis Serverへ接続

事の発端はLINE APIを触っていた時。
LINE API + Google App Engine + Pythonでボットを作成する

POSTされた値を処理した後にレスポンスを返すわけですが、処理に手間取るとタイムアウトするんじゃないか。
だったら、受け取ったPOSTデータを一旦退避してとりあえず200レスポンスを返す。
退避しておいたデータをじっくり眺めて処理すれば、タイムアウトを気にしなくてよいのでは。

というわけで、nginxをlua拡張モジュール付きでUbuntu Server 18.04にインストール。
Redisにpostされたデータを登録してみます。


nginx-extras



nginx-extrasをインストールすれば、lua拡張モジュール付きでビルドされた
nginxがインストールできます。
apt-getでDebian 8 + lua nginx moduleの環境構築(nginx-extras)


$ sudo apt install nginx-extras



動作確認のため、/etc/nginx/sites-available/defaultを編集。


$ sudo vi /etc/nginx/sites-available/default



locationの部分を編集します。


  1.         location / {
  2.                 default_type 'text/plain';
  3.                 content_by_lua "ngx.say('Hello,lua!')";
  4.         }



nginxの設定ファイルをリロード


$ sudo service nginx reload



ブラウザでアクセスしてみます。

877_01.png

luaが動いていますね。



スクリプトファイルの準備とデバッグ設定



毎回nginxの設定ファイルを変更するのは面倒なので、プログラム部分を別ファイルに記載できるようにします。
また、プログラムを書き換えるたびに設定ファイルをリロードするのも手間なので、
「lua_code_cache off」でスクリプトファイルをキャッシュしないよう指定しておきます。
※本番環境では使用しないほうが良いです。


  1.         location / {
  2.                 lua_code_cache off;
  3.                 default_type 'text/plain';
  4.                 content_by_lua_file /var/dev/lua/sample.lua;
  5.         }



編集がおわったらリロード。


$ sudo service nginx reload



/var/dev/lua/sample.luaにプログラムを記載してみます。

・sample.lua


  1. ngx.say('Hello, from script')



877_02.png

ちゃんと読み込まれていますね。



lua-nginx-redis



redisへの接続はlua-nginx-redisを使ってみます。
https://github.com/openresty/lua-resty-redis

aptでインストール。


$ sudo apt install lua-nginx-redis



サンプルを実行してみます。


  1. local redis = require "nginx.redis"
  2. local r = redis:new()
  3. -- データベース接続
  4. local ok, err = r:connect("127.0.0.1", 6379, 0)
  5. if not ok then
  6.     ngx.say("failed to connect: ", err)
  7.     return
  8. end
  9. -- データ登録
  10. ok, err = r:set("dog", "an animal")
  11. if not ok then
  12.     ngx.say("failed to set dog: ", err)
  13.     return
  14. end
  15. -- データ取得
  16. local res, err = r:get("dog")
  17. if not res then
  18.     ngx.say("failed to get dog: ", err)
  19.     return
  20. end
  21. if res == ngx.null then
  22.     ngx.say("dog not found.")
  23.     return
  24. end
  25. -- 取得したデータを表示
  26. ngx.say("dog: ", res)



877_03.png

いい感じです。



postデータの登録



postされたデータを登録してみます。
過去記事が参考になりました。
nginx + luaで簡易ファイルストレージ

・sample.lua


  1. local method = ngx.req.get_method()
  2. if method ~= 'POST' then
  3.     ngx.say('post only')
  4.     return
  5. end
  6. -- bodyの解析
  7. ngx.req.read_body()
  8. -- body_dataを取得してみる
  9. local req_body = ngx.req.get_body_data()
  10. -- 取得できなかったら、ファイルに保存されている
  11. if not req_body then
  12.     -- テンポラリファイル名を取得
  13.     local req_body_file_name = ngx.req.get_body_file()
  14.     -- 内容をすべて読み込み
  15.     local file = io.open(req_body_file_name, 'rb')
  16.     req_body = file:read('*a')
  17.     file.close()
  18. end
  19. local redis = require "nginx.redis"
  20. local r = redis:new()
  21. -- データベース接続
  22. local ok, err = r:connect("127.0.0.1", 6379, 0)
  23. if not ok then
  24.     ngx.say("failed to connect: ", err)
  25.     return
  26. end
  27. -- データ登録
  28. ok, err = r:set("body", req_body)
  29. if not ok then
  30.     ngx.say("failed to set body: ", err)
  31.     return
  32. end
  33. ngx.say('ok')



データ登録用のPythonスクリプトです。

・post.py


  1. # -*- coding:utf-8 -*-
  2. import urllib.request
  3. import json
  4. # 登録用のデータ
  5. data = {
  6.     'num' : 105,
  7.     'alphabet' : 'alphabet-value',
  8.     'str': '日本語登録テスト'
  9. }
  10. # JSON形式の文字列を取得
  11. jsonstr = json.dumps(data).encode("utf-8")
  12. url = 'http://192.168.1.102/'
  13. request = urllib.request.Request(url, data=jsonstr, method='POST')
  14. request.add_header('Content-Type', 'application/json')
  15. # 登録実行
  16. response = urllib.request.urlopen(request)
  17. ret = response.read()
  18. print('Response:', ret)



実行すると「ok」と応答が帰ってきました。


$ python3 post.py
Response: b'ok\n'



次はredisに登録されているはずのpostデータを取得してみます。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import redis
  4. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  5. rawdata = r.get('body')
  6. data = json.loads(rawdata)
  7. print(data['num'])
  8. print(data['alphabet'])
  9. print(data['str'])



実行結果


$ python3 sample.py
105
alphabet-value
日本語登録テスト



ちゃんとpostされたデータをredis経由で取得できました。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/05/06(日) 15:52:02|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Ubuntu 18.04に.NET Core 2をインストールしてC#プログラムをビルドする | ホーム | Python3からRedis Server 4へ接続する(redis-py使用)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
https://symfoware.blog.fc2.com/tb.php/2177-7f580f96
この記事にトラックバックする(FC2ブログユーザー)