.NET WindowsプロジェクトでTarantoolを使用する

最近、HabréにはTarantoolについての非常に多くの記事が掲載されています。Tarantoolは、さまざまな負荷の高いプロジェクトで、Yavi、AitoのMail.Ru Groupで使用されているデータベースおよびアプリケーションサーバーです。 それで、私が時々アドバイスする小さなスタートアップで、美しいが、残念ながら、モノリシックなアプリケーションをマイクロサービスに分離する必要があったとき、私は考えました:なぜ他の会社より悪いのか? -そして、タランツールに目を向けることにしました。 ただし、Tarantoolが使用されているほとんどの企業とは異なり、この場合、プロジェクトはWindows上のVisual Studioで開発されています。 マイクロサービスアーキテクチャに移行しても、ほとんどのマイクロサービスはC#で記述されると想定されています。 そして、Tarantool ...公式ウェブサイトにアクセスする価値があり、すぐに理解できます。WindowsにTarantoolをインストールすることでさえ、このオペレーティングシステムに移植されないため、問題があります。 このような困難にどのように取り組んだか、どのマイクロサービスTarantoolを選択したか、そして.NETプロジェクトでTarantoolをどのように使用できるかについては、この記事で説明します。 それまでの間、ネタバレ-ほとんどすべての困難は克服可能であり、私の経験は疑いなくポジティブと呼ぶことができます。 たとえば、Tarantoolをダウンロードして実行し、C#コードからリクエストを行うのに10分もかかりませんでした。 そして、その方法をお見せします!


画像


この記事は、Tarantoolの使用方法を説明するチュートリアルです。 Tarantoolで構築されたプロジェクトの説明や、Tarantoolと他の製品との比較はありません(このトピックについては、すでに多くの記事が執筆されています)。 この資料は、質問に答える試みとして生まれました。最初にTarantoolを使い始めたとき、何を読みたいですか。 しかし、最初に、実際にTarantoolを実際に使用していることについて少しお話しします。


計画



Tarantoolを使用する


ほとんどすべてのプロジェクトで最も重要なマイクロサービスの1つ(および私が最も懸念していた作成)は、認証と承認のマイクロサービスです。 そして何よりもまず、ユーザー情報が保存されるシステム/データベースに課せられる要件を決定する必要がありました。 それほど多くの要件はありませんが、実際には、市場で入手可能な非常に少数の製品がそれらを満たします。 さらに、構成とサポートを簡素化するために、これらの製品の最小量で常に対処する必要があります。 したがって、MySQL + Redis + RabbitMQなどの組み合わせ-これは明らかに多すぎるでしょう。 したがって、基本的な要件は次のとおりです。



Tarantoolは、その特性上、キャッシュ用のインメモリデータベースと、永続的で信頼性の高いデータストレージ用の本格的なNoSQL DBMSの非常に優れた組み合わせです。 さらに、すべての要件に適合し、適切なパフォーマンスを提供します。 したがって、これらと他の特性を比較した後、私たちは彼に有利な選択をしました。 しかも、さまざまなシステムの動物園全体をセットアップするのではなく、1つの優れたソリューションでタスクを取り除くことは常に素晴らしいことです。


マイクロサービスの承認と認証に関する重要なポイント。 ユーザーとグループに関するデータをディスクDBMSに保存することはできず、このデータをメモリ内キャッシュに取り込んで配置することはできません。 この場合のキャッシュには、メインデータベースとの高速で信頼性の高い同期メカニズムが必要です。 結局のところ、キャッシュとメインデータベースがまだ同期されていないために、ブロックされたユーザーが作業を続けることができないようにする必要があります。 同じ理由で、新しいユーザーはログインできません。 さらに、開発者として、私は本当にそのような同期のロジックを自分で書きたくありません。ソリューションの信頼性は疑わしく、逆に同期エラーの可能性は高いです。 したがって、TarantoolにWAL(先行書き込みログ)があり、ディスク上のデータとメモリ内のデータが常に同期されているという事実は、単に大きな利点です。 これはおそらく、Tarantoolを選択する最も重要な理由の1つです。 もちろん、パフォーマンスも別の重要な理由です。


それで、実際には、WindowsでTarantoolをどのように起動したかについてのストーリー自体を共有する時が来ました。 その後、.NETアプリケーションからTarantoolを操作する方法についてチュートリアル形式で説明します。


WindowsでTarantoolを使用する


Node.jsが人気を博したとき、そのWindowsバージョンは存在しませんでした。 そして、私たち、Windowsに座っている開発者は、待つか、ひざを噛むか、Macに切り替えるだけでよく、多くの人が時間をかけてやっていました。 現在、Microsoftは開発者がmacOSおよびLinux環境に慣れていることを理解しており、Windowsに引き戻すことはほぼ不可能です。 さらに、たとえ成功したとしても、開発者は多くを見逃します。 Microsoftがそれを推論したかどうかはわかりませんが、Windows 10では、エミュレーションまたは仮想化なしで、異なるLinuxディストリビューション(最初はUbuntuのみがサポートされ、現在はSuSeが利用可能)から変更されていない実行可能ファイルを実行することが可能になりました-Windows Subsystem for Linux(WSL)。 新しいWindowsカーネルサブシステムは、Linuxカーネルへの呼び出しを実装します。また、最小限の/ pico-processメカニズムにより、ntdllをロードしたり、他のWindows固有のものを実行したりすることはできません。 この機能は、2016年夏のWindows 10 Anniversary Updateに登場しました。 しかし、このバージョンではあまり機能しなかったため、この方法でTarantoolを実行する場合は、Fast Insider PreviewまたはWindows 10 Creators Updateの最新ビルドが利用可能になったときに使用することをお勧めします。 この記事を書いたときにこれを行いました(ビルド15031を使用しました)。 アセンブリ15031では、Tarantoolは多少のエラーはありますが、重要ではなく、一般に安定しています。 Windowsの以前のビルドでは、スタートアップにも問題がありました。


当然、Linux用のWindowsサブシステムについて話すときは、開発目的のためだけにこれを考慮します。 本番環境のWindows Serverでは、このようなソリューションは機能しません。 ネイティブサポートなしで行う方法はありません。 したがって、実稼働環境では、Dockerコンテナーで実行されるTarantoolを使用します。 コンテナーは、Azure Container Serviceで機能します。 実際、ASP.NET Coreマイクロサービスも同じ場所で機能するため、プロジェクトに新しいエンティティを実装する必要はありませんでした。 Dockerの使用はVisual Studio 2017で完全にサポートされており、開発中に非常に役立ちます。 しかし、Dockerは非常に優れているため、すべてをDigital Ocean、Amazon Lightsailに簡単に転送できます。 クラウドプロバイダーへのバインドはありません。


Dockerはまだ運用環境で使用されているため、開発中にDockerを使用することをお勧めします。 私の経験では、Windows上のDockerはmacOS上のDockerより悪くありません。 当然、これは(macOSのように)仮想化を使用しますが、この方法でプロジェクトを展開するときに多くの互換性の問題を取り除きます。 さらに、Dockerと完全に連携するには、Insider Previewの最新ビルドやWindowsの最新バージョンは必要ありません。


したがって、LinuxのWindows SubsystemでTarantoolを起動することは、それがまったく可能であることの単なるデモンストレーションとして検討します(Tarantoolでの作業を学習するために、このソリューションも興味深いでしょう。さらに、何らかの理由でDockerを使用できないかどうかが便利ですあなたが望む)、しかし実際の開発のために、私はまだDockerをお勧めします。


Linux用Windowsサブシステム上のTarantool


さて、今度は、Windows Subsystem for Linuxを使用してWindows 10でTarantoolを起動する5つの簡単なステップです。 このプロセス全体で約15分かかりました。 しかし、ここでは、ハードウェアとインターネット接続の速度に大きく依存します。 また、Windows 10 Insider Previewビルド15031でこれらすべての操作を行ったことを思い出してください。


1. [スタート]メニューから、[ Settings -> Update and Security -> For developers開発者Settings -> Update and Security -> For developers ]を選択Settings -> Update and Security -> For developers 、開発者モードが有効になっていない場合は有効にします。


画像


2.その後、PowerShellを起動し、LinuxのWindowsサブシステムを有効にする簡単なコマンドを実行します( > -もちろん、コマンドプロンプトを入力する必要はありません)。


 > Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux 

画像


前の手順と同様に、再起動が必要です。


3.コマンドプロンプトを開き、 bashコマンドを実行します。 Ubuntuユーザーモードディストリビューションをダウンロードし、Linuxユーザーを作成し、パスワードを設定するよう求められます。 [スタート]メニューでUbuntuをインストールして構成すると、Windows上のUbuntuでBashを直接起動するためのタイルが表示されます。


画像


やった! これで本格的なBashができました。Ubuntuで利用可能なほぼすべてのソフトウェアを実行できます。最も重要なことは、 apt-getコマンドがサポートされていることです。 罪はこれを使用することではありません。Tarantoolをインストールしましょう。


4.公式WebサイトにあるUbuntuのインストール手順4.使用します。


https://tarantool.org/download.html


 curl http://download.tarantool.org/tarantool/1.7/gpgkey | sudo apt-key add - release=`lsb_release -c -s` # install https download transport for APT sudo apt-get -y install apt-transport-https # append two lines to a list of source repositories sudo rm -f /etc/apt/sources.list.d/*tarantool*.list sudo tee /etc/apt/sources.list.d/tarantool_1_7.list <<- EOF deb http://download.tarantool.org/tarantool/1.7/ubuntu/ $release main deb-src http://download.tarantool.org/tarantool/1.7/ubuntu/ $release main EOF # install sudo apt-get update sudo apt-get -y install tarantool 

Bashでこれらのコマンドを実行します。 これで、Tarantoolがインストールされました。 これで開始できます。


5.同じ名前のコマンドを使用してTarantoolを起動し5.


 > tarantool 

Tarantoolは、組み込み言語としてLuaを使用します。 インタプリタプロンプトが表示されます。


 tarantool> 

Luaの特徴的な機能:非常にシンプルな言語であり、基本的な機能を学ぶのに文字通り15分かかります。 私自身の経験から言えば、Tarantoolの例に含まれるほとんどすべてのコードを理解するには、 15分間のチュートリアルで十分です。


そのため、tarantoolコマンドを実行すると、Luaインタープリターが目の前で開きます。 次に、Tarantoolを構成し、boxというTarantoolメインライブラリを使用してポート3311で実行しbox


 tarantool> box.cfg({listen = 3311}) 

この場合、 cfg関数の唯一のパラメーターはパラメーターを持つテーブルであるため(LuaのテーブルはJavaScriptのオブジェクトに非常に似ており、リレーショナルDBMSのテーブルとは関係ありません)、括弧を省略して次のようにコードを記述できます。


 tarantool> box.cfg{listen = 3311} 

次に、データストレージ用のスペースを作成します。 Tarantoolのスペースは、MongoDBのコレクション、または他のDBMSのテーブルに類似しています。


 tarantool> box.schema.space.create('customers') 

また、最初のフィールドにプライマリインデックスを作成します(セカンダリインデックスと複合インデックスも作成できます)。


 tarantool> box.space.customers:create_index('primary', {type = 'tree', parts = {1, 'UNSIGNED'}}) 

customers:create_indexのコロンcustomers:create_indexオブジェクトの方向をエミュレートし、 selfパラメーターを正しく渡すために必要です。 次の2つの呼び出しは同等です(1つの場合はピリオド、もう1つの場合はコロンに注意してください)。


 tarantool> box.space.customers:select({}) 

そして


 tarantool> box.space.customers.select(box.space.customers,{}) 

次に、スペースのcustomersいくつかのレコードを挿入しcustomers 。 1つは明示的な主キーを使用し、もう1つは自動増分を使用します。


 tarantool> box.space.customers:insert{1, 'Sergey', 'Moscow'} tarantool> box.space.customers:auto_increment{'Ivan', 'San-Francisco'} 

ここで、すべてのエントリをリクエストします。


 tarantool> box.space.customers:select{} 

YAML形式のコンソールには、新しく追加された2つのエントリがありました。


画像


Tarantoolを使い始めたばかりの場合は、チュートリアルを読むことをお勧めします。 チュートリアルは簡単なコマンドを開始します:


 tarantool> tutorial() 

また、Habréでは、 Tarantoolアーキテクチャその機能 、およびそれを使用して作業をすばやく開始する方法を説明する優れた記事を見つけることができます。


そのため、たった5つの簡単な手順で、TarantoolをWindows Subsystem for Linuxと連携させることができました。 Tarantoolは、仮想化を使用せずにWindows上でプロセスとして実行されます。 ここで、Dockerを使用して同様の結果を達成する方法を理解します。


Windows上のDockerのTarantool


インフラストラクチャーの観点から見ると、Dockerは過去10年間に業界で起こった最高のことのようです。 これで、単純なdocker runを使用して、長いセットアップなしでほとんどすべての製品を試すことができます。 そして、タランツールも例外ではありません。 したがって、 Docker for Windowsをインストールします (インストールされていない場合)。コンソールに移動して、次のコマンドを入力します。


 > docker run --name mytarantool -d tarantool/tarantool:1.7 

Tarantool 1.7イメージがまだダウンロードされていない場合は、自動的にダウンロードされ、このイメージから作成された新しいコンテナーが起動されます。 それだけです Tarantoolを開始しました! -d (分離) -dは、コンテナをバックグラウンドで実行する必要があることを示し-d 。 したがって、コマンドの実行後にコンソールに表示されるのは、コンテナーIDのみです。


ここで、独自のコンソールを介して新しいTarantoolインスタンスに接続します。


 > docker exec -it mytarantool console 

mytarantoolという名前のコンテナに接続し、その中でconsoleコマンドをインタラクティブに実行します。 その後、Tarantoolコンソールが開き、任意のコマンドを実行できます。


ご覧のとおり、Dockerをインストールした後、Tarantoolを起動するには1つのアクションが必要でした。Tarantoolに接続するには、もう1つのコマンドが必要です。 これは、Linux用Windowsサブシステムを使用した前の例よりもさらに簡単です。 それが、Dockerオプションを好む理由です。 それに加えて、DockerのTarantoolは本番環境で動作するのと同じ環境で動作します。


画像


TarantoolインスタンスがDocker上で稼働しています。 そして、彼はどこかにデータを保存しますが、それはすでに悪くはありません。 唯一の問題は、データの保存場所が正確にわからないことです。 Tarantoolがログとスナップショットを保存するWindowsホスト上の場所を指定する必要があります。 また、特定のポート(たとえば3301)でWindowsからTarantoolにアクセスできるようにする必要があります。これはすべて、 localhost:3301を使用して.NETアプリケーションから接続できるようにするために必要です。


ただし、これを行う前に、既存のコンテナを停止して削除します。


 > docker stop mytarantool && docker rm mytarantool 

フォルダC:\tarantool\data作成します。これは、Tarantoolインスタンスのログとスナップショットをホストします。 フォルダの名前と場所は任意に選択されます。 フォルダーにDockerでアクセスできるディスクを作成することを忘れないでください。システムトレイのDockerアイコンをクリックし、コンテキストメニューで[ Settings… ]を選択し、開いた[ Shared Drivesセクションで必要なディスクを選択します。


画像


Tarantoolで新しいDockerコンテナーを起動します。


 > docker run --name mytarantool -d -p 3301:3301 -vc:/tarantool/data:/var/lib/tarantool tarantool/tarantool:1.7 

WindowsのC:\tarantool\dataフォルダーを/var/lib/tarantoolコンテナー-(コンテナーの設定に従って)データが保存される場所に/var/lib/tarantoolしました。 コンテナを起動すると、 C:\tarantool\dataフォルダにログファイルとスナップショットが表示されたことがわかります。


画像


TarantoolがWindowsからlocalhost:3301で利用できるようになりました。 .NETアプリケーション(またはその他)からアクセスできます。 唯一の問題は、Tarantoolが現在空であることです。 space'yを作成し、必要に応じてデータを追加します。 また、ユーザーを作成し、権利を割り当てます。 コンソールでこれを手動で行うことはお勧めできません。そのため、Luaで初期化スクリプトを作成してみましょう。 次のセクションで本格的なLua初期化スクリプトの作成を詳細に検討しますが、ここでは、さらに改善する最小限のスクリプトを作成しましょう。 これを行うには、フォルダーC:\tarantool\appとその中にファイルapp.init.luaを作成します。 現在、構成の詳細はあまり重要ではありません。 作成する最小限のLuaスクリプトは次のとおりです。


app.init.lua


 #!/usr/bin/env tarantool box.cfg { pid_file = nil, background = false, log_level = 5 } 

また、Dockerコンテナーを起動するには、毎回複雑なコマンドを入力する必要はありません。 したがって、Docker Composeを使用して、 C:\tarantool\配置したYAMLファイルdocker-compose.ymlに構成全体を書き込みましょう。


docker-compose.yml


 version: '2' services: tarantool: container_name: mytarantool image: tarantool/tarantool:1.7 command: tarantool /usr/local/share/tarantool/app.init.lua ports: - 3301:3301 volumes: - c:/tarantool/app:/usr/local/share/tarantool - c:/tarantool/data:/var/lib/tarantool 

ここで、 tarantool/tarantool:1.7からtarantoolという名前のtarantoolサービスを作成します。 同時に、起動時に構成ファイルapp.init.luaを引数として転送し、ポート3301でWindowsからTarantoolを使用できるようにします。さらに、WindowsフォルダーappdataをDockerコンテナーにリンクします。


これで、Docker Composeを使用して1つの簡単なコマンドでTarantoolを起動できます。


 > docker-compose -f C:/tarantool/docker-compose.yml up -d 

次のコマンドを使用して、Tarantoolでコンテナを停止および削除できます。


 > docker-compose -f C:/tarantool/docker-compose.yml down 

既にdocker-compose.ymlファイルがあるフォルダーにいる場合は、ファイルパスをdocker-compose.ymlできます。


 > cd C:/tarantool/ > docker-compose up -d 

じゃあ 1つのdocker docker-compose起動するようにTarantoolを構成し、簡単な初期化スクリプトを作成しました。 現在、フォルダ構造は次のとおりです。


画像


ユーザー、スペース、ロードテストデータを作成する、より高度な初期化スクリプトを作成します。


初期化スクリプトを作成


初期化スクリプトは次のことを行います。 まず、パスワード123123 operatorユーザーを作成します。 このユーザーには、読み取り、書き込み、および実行の許可が付与されます。 次に、スペースusers作成しusers 。 また、3つのインデックス:ユーザーIDがGUID文字列として保存される最初のフィールドの一意のインデックス(フィールドはゼロではなく1からカウントされます)、ログインが保存される3番目のフィールドの一意のインデックス、および5番目のフィールドの一意でないインデックスユーザー評価は数値として保存されます。 ユーザー、スペース、インデックスの作成は、 init関数で行われます。 そして、 load_data関数では、ユーザースペースに3つのエントリを追加します。 box.once関数を使用box.onceと、現在のデータベースに対して関数を1回実行できbox.onceが、これは非常に便利な機能のようです。 以下は、完全なapp.init.luaコードです。


app.init.lua


 #!/usr/bin/env tarantool local log = require('log') local uuid = require('uuid') local function init() box.schema.user.create('operator', { password = '123123', if_not_exists = true }) box.schema.user.grant('operator', 'read,write,execute', 'universe', nil, { if_not_exists = true }) local users_space = box.schema.space.create('users', { if_not_exists = true }) users_space:create_index('primary_id', { if_not_exists = true, type = 'HASH', unique = true, parts = {1, 'STRING'} }) users_space:create_index('secondary_login', { if_not_exists = true, type = 'HASH', unique = true, parts = {3, 'STRING'} }) users_space:create_index('secondary_rating', { if_not_exists = true, type = 'TREE', unique = false, parts = {5, 'INT'} }) end local function load_data() local users_space = box.space.users users_space:insert{uuid.str(), 'Ivan Ivanov', 'ivanov', 'iivanov@domain.com', 10} users_space:insert{uuid.str(), 'Petr Petrov', 'petrov', 'ppetrov@domain.com', 15} users_space:insert{uuid.str(), 'Vasily Sidorov', 'sidorov', 'vsidorov@domain.com', 20} end box.cfg { pid_file = nil, background = false, log_level = 5 } box.once('init', init) box.once('load_data', load_data) 

app.init.luaファイルを変更し、TarantoolコマンドでDockerコンテナーを再起動します。


 > docker-compose restart 

これで、.NETアプリケーションから操作できるデータを備えた完全に機能するTarantoolができました。


.NET / C#でのTarantoolの使用C#


.NETアプリケーションでTarantoolを操作するための最も一般的なライブラリは、 ProGaudi / tarantool-csharpライブラリです。これについては、このセクションで説明します。


GitHubのこのライブラリのリポジトリには、Dockerを使用してTarantoolと連携する ASP.NET Coreアプリケーションの優れた例があります。 この例では、おなじみのTarantoolセットアップとDocker Composeが表示されます。 ダウンロードして例を見ることをお勧めしますが、今度はよりシンプルなコンソールアプリケーションを見ていきます。


この記事で説明したすべてのコードとプロジェクトは、 GitHubにあります


Visual Studioで新しいコンソールアプリケーションを作成し、NuGetを使用してtarantool-csharpをプラグインします。 これを行うには、 Solution ExplorerウィンドウのプロジェクトのコンテキストメニューからManage NuGet packages…選択Manage NuGet packages…ますManage NuGet packages…次に、 Tarantool.CSharpパッケージを見つけてインストールします。


画像


データサンプリング


これで、C#コードからTarantoolへの最初のリクエストの時間です。 Tarantoolにリクエストを行います。これは、Dockerコンテナの前のセクションで起動し、 app.init.luaスクリプトを使用して設定します。 スクリプトでは、パスワード123123使用してユーザーuserを作成しました。 以下は、Tarantoolに接続し、 usersとプライマリインデックスprimary_idからスペースを取得し、このインデックスによってすべてのレコードを取得するためのコードです。


 using System; using System.Threading.Tasks; using ProGaudi.Tarantool.Client; using ProGaudi.Tarantool.Client.Model; using ProGaudi.Tarantool.Client.Model.Enums; namespace ConsoleApp { class Program { static void Main(string[] args) { DoWork().Wait(); } static async Task DoWork() { using (var box = await Box.Connect( "operator:123123@localhost:3301")) { var schema = box.GetSchema(); var space = await schema.GetSpace("users"); var primaryIndex = await space.GetIndex("primary_id"); var data = await primaryIndex.Select<TarantoolTuple<string>, TarantoolTuple<string, string, string, string, long>>( TarantoolTuple.Create(String.Empty), new SelectOptions { Iterator = Iterator.All }); foreach (var item in data.Data) { Console.WriteLine(item); } } } } } 

ほとんどのコードは、それ自体を物語っています。 Select機能について詳しく見ていきたいと思います。 この関数では、選択が発生するキーのタイプと戻り値のタイプを指定する必要があります。 文字列に格納されたGUIDは識別子であるため、キータイプとしてTarantoolTuple<string>指定する必要があります。


ユーザーデータには、4つのテキストフィールドと1つの数値という、ID、名前、ログイン、メール、評価が含まれます。 したがって、 TarantoolTuple<string, string, string, string, long>戻り型として指定されます。


タイプが示されると、 Select機能は次のようになります。


 primaryIndex.Select<TarantoolTuple<string>, TarantoolTuple<string, string, string, string, long>>(...) 

次に、 Select関数に引数が渡されます。 最初の引数は、空の文字列TarantoolTuple.Create(String.Empty)を含むタプルです。 ここで、ユーザーごとに選択する場合、特定のユーザーのIDを渡すことができます。 ただし、空の文字列をキーとして使用すると、すべてのレコードを一度に取得できます。 また、 SelectOptions型のパラメーターを使用してすべてのレコードを取得する必要があることも示しています。このパラメーターでは、 Iterator.Allを反復子として設定します。


この例では、DoWork関数がDoWorkたびにTarantoolへの新しい接続を作成します。 実際、リクエストごとに新しい接続を作成する必要はありません。1つの接続を完全に再利用できます。


アプリケーションを起動し、宇宙usersすべてのusersが表示されていることを確認します。


画像


データを追加する


次に、スペースusers新しいエントリを追加しusers 。 エントリを追加するには、5つのフィールドで構成されるタプルを作成します。 最初のフィールドの値として、新しいGUIDを生成します。


 await space.Insert(TarantoolTuple.Create(Guid.NewGuid().ToString(), "Vladimir Vladimirov", "vvladimirov", "vvladimirov@domsin.com", 10L)); 

データ更新


更新は選択とほぼ同じに見えます。 さらに、 Updateは更新された値を返すので、選択のようになります。 以下のコードでは、指定されたIDを持つユーザーに新しい評価値を割り当てます。


 var updatedData = await space.Update<TarantoolTuple<string>, TarantoolTuple<string, string, string, string, long>>( TarantoolTuple.Create("4e574d2f-1c82-4e14-aba8-95c6412e357c"), new UpdateOperation[]{ UpdateOperation.CreateAssign<long>(4, 47L) }); 

二次キーのサンプル


プライマリキーに加えて、セカンダリキーをリクエストできます。 次の例は、セカンダリインデックスsecondary_loginによる値petrov持つレコードの検索(つまり、この場合のログインフィールドによる検索)を示しています。


 var loginIndex = await space.GetIndex("secondary_login"); var users = await loginIndex.Select<TarantoolTuple<string>, TarantoolTuple<string, string, string, string, long>>( TarantoolTuple.Create("petrov")); var petrov = users.Data; 

評価が15の( Ge -Greater or Equal)以上のすべてのユーザーを検索します。


 var ratingIndex = await space.GetIndex("secondary_rating"); var ratingUsers = await ratingIndex.Select<TarantoolTuple<long>, TarantoolTuple<string, string, string, string, long>>( TarantoolTuple.Create(15L), new SelectOptions { Iterator = Iterator.Ge }); 

Lua関数の呼び出し


SelectInsertUpdateなどの関数を使用してC#コードからデータを操作することに加えて、多くの場合、データをできるだけ近くで処理する必要があります。 データに最も近い場所はTarantoolサーバーです。 サーバー上のすべてのユーザーの評価を直接増加させる関数をLuaで作成しましょう。 update_ratingupdate_ratingます。 この関数は、数行で構成されています。 まず、 pairs()関数を呼び出すことにより、 users空間の反復子を取得します。 そして、イテレータを反復処理します。 各レコードは、評価値が1ずつ増加して更新されます。 以下は機能コードです。 app.init.luaファイルの最後に追加し、 app.init.lua Dockerコンテナーを再起動します。 もちろん、コンテナを再起動することは本番環境にとって最適なソリューションではありませんが、開発とデバッグを行う場合は最速のオプションです。


app.init.lua


 function update_rating() for k,v in box.space.users:pairs() do box.space.users:update(v[1], {{'+', 5, 1}}) end end 

次に、C#からupdate_rating Lua関数を呼び出します。


Program.cs


 await box.Call("update_rating"); 

アプリケーションに関数呼び出しを追加して実行します。 評価が更新されていることを確認してください。


Luaで関数を作成できることは、Tarantoolの大きな利点の1つです。 このような関数は、Tarantoolとクライアントアプリケーション間でデータを転送する必要なく、複雑なデータ処理を実行できます。 さらに、Tarantoolはそれ自体がアプリケーションサーバーでもあるため、C#、Java、Go、PHPまたは他の言語のサードパーティコードを必要とせずに、Tarantoolでのみ動作するマイクロサービスを作成できます。 このようなマイクロサービスは通常、REST APIを提供します。これはLuaコードでのみ実装することもできます。


.NETアプリケーションからTarantoolと対話する主な方法を検討した後、ProGaudi / tarantool-csharpを使用した印象についてお話します。


ProGaudiの印象/ tarantool-csharp


ProGaudi / tarantool-csharpを使用するという二重の印象を受けました。 一方、ライブラリを使用すると、通常のアプリケーションに必要なほぼすべてのクエリを実行できます。 何かがサポートされていない場合は、Luaで関数を記述できます。これにより、C#コードから簡単に呼び出すことができます。 一方で、ライブラリはもちろん低すぎます。 多くの定型的なヘルパーコードが必要です。 また、優れたORM(オブジェクトリレーショナルマッパー)が明確に不足しているため、ダミーではなくドメインクラスの観点からコードを記述できます。 したがって、私自身は、タランツールのORMがどのように見えるかを考えることにしました。 このアイデアはまだ初期段階にあり、提案や提案を歓迎します。 そして、私は本当にこのようなことをしたいと思います:


 public class User { public string Id { get; set; } public string Name { get; set; } public string Login { get; set; } public string Email { get; set; } public long Rating { get; set; } } private static async Task DoWork() { var box = (await Box.Connect( "operator:123123@localhost:3301")).Wrap(); var space = box.Space("users"); var primaryIndex = space.Index("primary_id"); var ratingIndex = space.Index("secondary_rating"); var all = await primaryIndex.Select<User>(); var user = await primaryIndex.Select<User>("f73ee542-7d3e-4dec-b7c6-ce5dc7a02920"); var top = await ratingIndex.Select<User>(20, Iterator.Ge); var low = await ratingIndex.Select<User>(20, Iterator.Lt); } 

この方法で記述できるコードは、 ここにあります 。 APIがどのように見えるかを示すために、ひざの上でプロトタイプとして作成されていることを警告します。 したがって、実際のプロジェクトでコードを使用することは絶対にお勧めしません。 近い将来、ORMプロトタイプをGitHubの完全なリポジトリに配置したいと考えています。


TarantoolでのRESTサービスの作成


Tarantoolを使用すると、多くの場合、Tarantool自体に多くの問題を解決するのに十分な機能があり、たとえば追加のC#コードには必要がないという感覚を覚えます。 この記事で説明されているマイクロサービスを利用してください。 他のマイクロサービスが呼び出すREST APIを提供する必要があります。 最初は、ASP.NET Web APIの機能を使用するASP.NET Coreアプリケーションがマイクロサービスとして機能する必要があると想定されていました。 そして、すでにアプリケーション自体のコードはTarantoolに訴えかけるでしょう。 しかし、判明したように、ASP.NET Coreアプリケーションは、マイクロサービスユーザーとTarantoolの間でデータを転送する以外、ほとんど何もしません。 , Tarantool REST API . , .


REST- GET - — /users . , . , Tarantool .


REST- 8080. Windows 8080 Docker-. docker-compose.yml :


docker-compose.yml


 ports: - 3301:3301 - 8080:8080 

Tarantool http.server , Docker-, . app.init.lua :


app.init.lua


 local function users_handler(self) local data = { users = {}, count = box.space.users:len() } for k, v in box.space.users:pairs{} do table.insert(data.users, { id = v[1], user = v[2] .. ' (' .. v[3] .. ')' , rating = v[5] }) end return self:render{ json = data } end local httpd = require('http.server') local server = httpd.new(nil, 8080, { app_dir = '/usr/local/share/tarantool/' }) server:route({ path = '/', file = 'index.html.el' }) server:route({ path = '/users' }, users_handler) server:start() 

: /users . index.html.el (el — embedded Lua.), /users users_handler . — space users , ID , , . JSON. JSON :


 { "count":3, "users":[ { "user":"Ivan Ivanov (ivanov)", "rating":10, "id":"c371b2b1-5090-450b-8a5d-7dba87ad5116" }, { "user":"Petr Petrov (petrov)", "rating":15, "id":"b4f80aad-f3c2-42b0-8088-84846aef9997" }, { "user":"Vasily Sidorov (sidorov)", "rating":20, "id":"07c82a50-4d8c-489a-9cc1-b4fdd95afbd8" } ] } 

index.html.el C:\tarantool\app\templates . :


画像


index.html.el REST API .


index.html.el


 <!DOCTYPE html> <html lang="en"> <head> <title>Users Dahsboard</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="page-header"> <h1>Users Dasbboard</h1> </div> <table class="table" id="tblUsers"> <thead> <tr> <th>#</th> <th>Id</th> <th>User</th> <th>Rating</th> </tr> </thead> </table> </div> <script> fetch('/users').then(resp => { resp.json().then(data => { function createCell(tr, txt){ tr.insertCell().appendChild( document.createTextNode(txt)); } let tblUsers = document.getElementById('tblUsers'); for(let i=0;i<data.users.length;i++){ var tr = tblUsers.insertRow(); createCell(tr, i + 1); createCell(tr, data.users[i].id); createCell(tr, data.users[i].user); createCell(tr, data.users[i].rating); } }); }); </script> </body> </html> 

JavaScript- , . , Fetch API .


, REST API . JSON . , Postman .


画像


. .


画像


まとめ


, Tarantool . Tarantool — , , Windows-. , Tarantool . , , . .


, . , Tarantool , .


, C# Tarantool , . ORM.


, , GitHub .


よろしくお願いします!



Source: https://habr.com/ru/post/J321998/


All Articles