Tarantoolのアプリケーションは、基本的にAPIとして使用されるストアドプロシージャのコレクションです。 データはストレージ側で処理されるため、パフォーマンスが大幅に向上します。 ただし、ストアドプロシージャのサポートは悪夢のようです。
たぶん。 しかし、今日ではありません。
今日は、アプリケーションの品質を確保する問題を検討します。 特に、テストについて説明し、生産を開始する方法、コネクタを使用する方法を確認し、データスキームの移行の複雑さについても説明します。
Tarantoolアプリケーションシリーズの内容
- パート1:ストアドプロシージャ
- パート2:OAuth2認証
- パート3:テストと起動
この連載のすべての例は、 tarantool-authmanユーザー認証アプリケーションに基づいていることを思い出させてください。
テスト中
テストは、品質を改善するための1つの方法にすぎません。
ストアドプロシージャの場合、機能テストは現在のAPIをサポートするための優れたオプションです。 テストには、Tarantoolに組み込まれたtap(Test Anything Protocol)モジュールが使用されます。 これには、Luaオブジェクトの基本的なチェックと比較のためのいくつかのメソッドが含まれています。 ユーザー登録auth.registration(email)
2つのケースをテストしてみましょう。
local case = {} local tap = require('tap') local response = require('authman.response') local error = require('authman.error') local db = require('authman.db') local config = require('test.config') -- local auth = require('authman').api(config) local test = tap.test('registration_test') -- space function case.before() db.truncate_spaces() end function case.after() end function test_registration_succes() local ok, code ok, code = auth.registration('test@test.ru') -- , , — test:is(ok, true, 'test_registration_succes user created') test:isstring(code, 'test_registration_succes code returned') end function test_registration_user_already_exists() local ok, code, got, expected, user ok, code = auth.registration('test@test.ru') -- API, ok, user = auth.complete_registration('test@test.ru', code, 'password') -- , -- , Lua- got = {auth.registration('test@test.ru'), } expected = {response.error(error.USER_ALREADY_EXISTS), } -- is_deeply Lua- test:is_deeply(got, expected, 'test_registration_user_already_active') end case.tests = { test_registration_succes, test_registration_user_already_exists } return case
次に、テストを実行する小さなスクリプトを作成します。 before
メソッドとafter
メソッドを考慮することを忘れないでください。これにより、テストが簡単になります。
-- , Tarantool box.cfg { listen = 3331, } local TEST_CASES = { 'test.case.registration', } function run() for case_index = 1, #TEST_CASES do local case = require(TEST_CASES[case_index]) for test_index = 1, #case.tests do -- case.before() case.tests[test_index]() case.after() end end end run()
テスト実行結果:
$ tarantool test/authman.test.lua ... TAP version 13 ok — test_registration_succes user created ok — test_registration_succes code returned ok — test_registration_user_already_active
インスタンスの起動
アプリケーションは作成およびテストされています。つまり、実稼働環境にデプロイする時間です。
Tarantoolインスタンスは、 組み込みのtarantoolctlユーティリティを使用して管理されます 。 まず、アプリケーションでインスタンスを作成します。 ユーザーを追加して権限を与えることを忘れないでください。
box.cfg { listen = 3331; } local function bootstrap() box.schema.user.create('my_user', {password = '123'}) box.schema.user.grant('my_user', 'read,write,execute', 'universe') end box.once('init_user', bootstrap) config = { -- } -- auth auth = require('auth').api(config)
次に、instances.enabledディレクトリからこのファイルへのシンボリックリンクを作成します。
sudo ln -s /etc/tarantool/instances.available/auth.lua /etc/tarantool/instances.enabled/auth.lua
tarantoolctlを実行し、Tarantoolに接続してアプリケーションメソッドを使用できることを確認します。
$ tarantoolctl start auth $ tarantoolctl enter auth connected to unix/:/var/run/tarantool/auth.control unix/:/var/run/tarantool/auth.control> ok, user = auth.registration('ivanov@mail.ru') unix/:/var/run/tarantool/auth.control> ok, user = auth.complete_registration('ivanov@mail.ru', user.code, '123') unix/:/var/run/tarantool/auth.control> user --- - is_active: true email: ivanov@mail.ru id: 8cd27d26-3974-43d6-a2b2-87202664753d ...
問題が発生した場合は、ログ/var/log/tarantool/auth.lua
確認する必要があります。 Tarantoolサーバーの管理の詳細については、ドキュメントをご覧ください。
コネクター
ストアドプロシージャの利点の1つは、異なるプログラミング言語で記述されたサービスに共通のインターフェイスを提供することです。
Pythonコネクタを使用してTarantoolを非同期的に使用する例を考えてみましょう。
import asyncio import asynctnt async def create_user(): tnt_connection = asynctnt.Connection( host='127.0.0.1', port='3367', username='my_user', password='123' ) # user_data = await tnt_connection.call( 'auth.registrtion', ['exaple@mail.ru', ] ) await tnt_connection.disconnect() # loop = asyncio.get_event_loop() loop.run_until_complete(create_user())
組み込みのnet.box
モジュールを使用して、別のTarantoolインスタンスからTarantoolと対話することもできます。 詳細については、ドキュメントを参照してください 。
データ移行
アプリケーションがすでに戦闘で実行されている場合の一般的なタスクは、データスキームを変更することです。 たとえば、ユーザーはgender
フィールドを追加する必要があります。
これを行うには、スペースauth_user
すべてのデータを変更するスクリプトを作成します。 スクリプト自体をアプリケーション初期化呼び出しに追加でき、 box.once
関数box.once
繰り返し呼び出しbox.once
制限します。
local fiber = require('fiber') local function migrations() -- box.once('20171101_add_gender', function () local counter = 0 -- space -- for _, tuple in box.space.auth_user:pairs( nil, {iterator=box.index.ALL} ) do local user_tuple = tuple:totable() -- user_tuple[4] = get_user_gender() box.space.auth_user:replace(user_tuple) counter = counter + 1 end end) end migrations()
移行には長い時間がかかる場合がありますが、実行のメインスレッドはブロックされません。 これは、 replace
メソッドが暗黙的にyield
呼び出すyield
です。 実行スレッドを明示的に解放するには、 fiber.sleep(0)
メソッドを呼び出す必要があります。 詳細については、ドキュメントを参照してください 。
次は?
タランツールは静止しておらず、積極的に開発中です。
このチュートリアルシリーズの記事以外にも、独自のサービスを作成する際に注意すべき重要な問題がいくつかあります。
- シャーディングとレプリケーション。 vshardモジュールの使用。
- TarantoolでのSQL構文のサポート。 SQLを使用したストアドプロシージャの最適化。
- Vinyl Disk Engineの概要。 Memtxとの比較、または「RAMが終わったらどうなりますか?」
- Cで記述されたストアドプロシージャの最適化とプロファイリング
すべてのコード例はtarantool-authmanアプリケーションからのものであることを思い出してください。 また、開発中であり、現在はOauth2-serverとして使用できます。
記事シリーズの範囲を超える質問がまだある場合は、 電報チャットで質問することができます。 レスポンシブなTarantoolコミュニティはあなたを助けることができるでしょう。
第三部を待っていたすべての人に感謝します。
じゃあね!
Tarantoolコミュニティは、 6月21日にモスクワで最初のインメモリコンピューティング会議を開催します。 報告はまだ受け付けられており、論文の募集は開いています。