Symfoware

Symfowareについての考察blog

lua nginx moduleでMessagePackのデータを使用(lua-MessagePack)

lua nginx moduleでいろいろ試しています。
apt-getでDebian 8 + lua nginx moduleの環境構築(nginx-extras)
lua nginx moduleでjson形式のレスポンスを返す(cjson)
lua nginx moduleからMariaDB(MySQL)に接続する(lua-sql-mysql)

jsonの使い方に続き、MessagePackが使えるか調べてみます。


lua-MessagePackとluarocks



これでMessagePack形式のデータが扱えそうです。
lua-MessagePack

インストールにはluarocksを使うのが楽そう。
まず、aptでluarocksをインストールします。


# apt-get install luarocks



luarocksでlua-messagepackをインストール。


# luarocks install lua-messagepack
Installing https://rocks.moonscript.org/lua-messagepack-0.5.0-1.src.rock...
Using https://rocks.moonscript.org/lua-messagepack-0.5.0-1.src.rock... switching to 'build' mode
Updating manifest for /usr/local/lib/luarocks/rocks
lua-messagepack 0.5.0-1 is now built and installed in /usr/local (license: MIT/X11)



インストールできた模様。


nginxの設定ファイル(/etc/nginx/sites-available/default)の抜粋はこうなります。


    location / {
        lua_code_cache off;
        default_type 'application/octet-stream';
        content_by_lua_file /var/dev/lua/sample.lua;
    }




動作確認用に用意した/var/dev/lua/sample.lua


  1. local mp = require 'MessagePack'
  2. value = { true, { foo = "bar" } }
  3. mp_value = mp.pack(value)
  4. ngx.say(mp_value)




packでmessagepack形式に変換してくれます。
ブラウザで確認してみると、こんな表示になりました。

741_01.png



クライアントをPythonで記載してみます。
PythonでMessagePackを使用して、Mapのシリアライズと復元

pipでmsgpack-pythonをインストール。


$ sudo pip install msgpack-python




サンプルはこうなりました。


  1. # -*- coding:utf-8 -*-
  2. import urllib2
  3. import msgpack
  4. f = urllib2.urlopen('http://192.168.1.104/')
  5. packed = f.read().strip()
  6. ret = msgpack.unpackb(packed, encoding='utf-8')
  7. print ret




レスポンスデータの最後に改行が入ります。
stripで取り除いておかないと、こんなエラーになりました。


Traceback (most recent call last):
File "sample.py", line 8, in <module>
    ret = msgpack.unpackb(packed, encoding='utf-8')
File "msgpack/_unpacker.pyx", line 143, in msgpack._unpacker.unpackb (msgpack/_unpacker.cpp:2143)
msgpack.exceptions.ExtraData: unpack(b) received extra data.




実行してみると、ちゃんと復元できています。


$ python sample.py
[True, {u'foo': u'bar'}]








MariaDBからデータ取得



lua nginx moduleからMariaDB(MySQL)に接続する(lua-sql-mysql)
こちらのサンプルを流用し、jsonではなくmessagepack形式のデータに変更してみます。

lua側のプログラム


  1. local mp = require 'MessagePack'
  2. -- bodyの解析
  3. ngx.req.read_body()
  4. -- body_dataを取得してみる
  5. local req_body = ngx.req.get_body_data()
  6. -- もし取得できていなかったら、データはファイルに行っている
  7. if not req_body then
  8.     -- テンポラリのファイル名を取得。内容を全部読み込む
  9.     local req_body_file_name = ngx.req.get_body_file()
  10.     if req_body_file_name then
  11.         local file = io.open(req_body_file_name, 'rb')
  12.         req_body = file:read('*a')
  13.         file:close()
  14.     end
  15. end
  16. if not req_body then
  17.     ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  18. end
  19. -- postされた値を解析
  20. -- unpackでバイナリからオブジェクトに変換
  21. local post = mp.unpack(req_body)
  22. local driver = require 'luasql.mysql'
  23. env = assert (driver.mysql())
  24. con = assert (env:connect('sample', 'root', 'P@ssw0rd', 'localhost', 3306))
  25. -- 接続文字コードを変更
  26. assert (con:execute('SET NAMES utf8mb4'))
  27. -- 結果を取得
  28. result = {}
  29. cur = assert (con:execute(post.query))
  30. row = cur:fetch ({}, "a")
  31. while row do
  32. local copy_row = {}
  33. for field in pairs(row) do
  34. copy_row[field] = row[field]
  35. end
  36. table.insert(result, copy_row)
  37. row = cur:fetch (row, "a")
  38. end
  39. -- close everything
  40. cur:close() -- already closed because all the result set was consumed
  41. con:close()
  42. env:close()
  43. -- 結果セットをpackでバイナリに変換
  44. mp_raw = mp.pack(result)
  45. ngx.say(mp_raw)




クライアントとなるPython側のプログラム


  1. # -*- coding:utf-8 -*-
  2. import urllib2
  3. import msgpack
  4. data = msgpack.packb({u'query':u'select * from t where id = 2'})
  5. f = urllib2.urlopen('http://192.168.1.104/', data)
  6. mp_raw = f.read().strip()
  7. mp_data = msgpack.unpackb(mp_raw, encoding='utf-8')
  8. for row in mp_data:
  9.     print row['id'], row['value']




思いの外あっさり動きました。


$ python sample.py
2 日本語テスト2




関連記事

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

  1. 2017/04/09(日) 21:29:29|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Riot ajaxで取得したjsonデータをテーブルに表示する(axios使用) | ホーム | lua nginx moduleからMariaDB(MySQL)に接続する(lua-sql-mysql)>>

コメント

コメントの投稿


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

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1974-474fd2e7
この記事にトラックバックする(FC2ブログユーザー)