Tarantool میں، آپ ایک انتہائی تیز ڈیٹا بیس اور ان کے ساتھ کام کرنے کے لیے ایک ایپلیکیشن کو یکجا کر سکتے ہیں۔ یہاں یہ ہے کہ یہ کرنا کتنا آسان ہے۔

پانچ سال پہلے میں نے ترن ٹول کے ساتھ کام کرنے کی کوشش کی، لیکن پھر یہ میرے لیے کام نہیں کر سکا۔ لیکن حال ہی میں میں نے ایک ویبینار منعقد کیا جہاں میں نے Hadoop کے بارے میں بات کی اور MapReduce کیسے کام کرتا ہے۔ وہاں انہوں نے مجھ سے ایک سوال پوچھا: "کیوں نہیں اس کام کے لیے ترن ٹول کا استعمال؟"

تجسس کی وجہ سے، میں نے اس پر واپس آنے کا فیصلہ کیا، تازہ ترین ورژن کی جانچ کی - اور اس بار مجھے واقعی یہ پروجیکٹ پسند آیا۔ اب میں آپ کو دکھاؤں گا کہ ترن ٹول میں ایک سادہ ایپلیکیشن کیسے لکھی جائے، اسے لوڈ کریں اور اس کی کارکردگی چیک کریں، اور آپ دیکھیں گے کہ سب کچھ کتنا آسان اور ٹھنڈا ہے۔

Tarantool میں، آپ ایک انتہائی تیز ڈیٹا بیس اور ان کے ساتھ کام کرنے کے لیے ایک ایپلیکیشن کو یکجا کر سکتے ہیں۔ یہاں یہ ہے کہ یہ کرنا کتنا آسان ہے۔

ترنتول کیا ہے؟

ٹرانٹول خود کو ایک انتہائی تیز ڈیٹا بیس کے طور پر رکھتا ہے۔ آپ وہاں کوئی بھی ڈیٹا ڈال سکتے ہیں۔ اس کے علاوہ، ان کی نقل تیار کریں، شارڈ - یعنی ڈیٹا کی ایک بڑی مقدار کو کئی سرورز میں تقسیم کریں اور ان کے نتائج کو یکجا کریں - غلطی برداشت کرنے والے ماسٹر ماسٹر کنکشن بنائیں۔

دوم، یہ ایک ایپلیکیشن سرور ہے۔ آپ اس پر اپنی ایپلی کیشنز لکھ سکتے ہیں، ڈیٹا کے ساتھ کام کر سکتے ہیں، مثال کے طور پر کچھ اصولوں کے مطابق بیک گراؤنڈ میں پرانے ریکارڈز کو ڈیلیٹ کر سکتے ہیں۔ آپ ٹیرانٹولا میں براہ راست Http سرور لکھ سکتے ہیں جو ڈیٹا کے ساتھ کام کرے گا: ان کی مقدار بتا دیں، وہاں نیا ڈیٹا لکھیں اور یہ سب کچھ ماسٹر کے لیے کم کریں۔

میں نے اس بارے میں ایک مضمون پڑھا کہ کس طرح لڑکوں نے 300 لائنوں کی ایک پیغام کی قطار بنائی، جو کہ بس پھٹ رہی ہے اور تیزی سے چل رہی ہے - ان کی کم از کم کارکردگی 20 پیغامات فی سیکنڈ ہے۔ یہاں آپ واقعی گھوم سکتے ہیں اور ایک بہت بڑی ایپلیکیشن لکھ سکتے ہیں، اور یہ سٹوریج نہیں ہوگی، جیسا کہ PostgreS میں ہے۔

میں اس مضمون میں اس سرور کی طرح کچھ، صرف سادہ، بیان کرنے کی کوشش کروں گا۔

تنصیب

ٹیسٹ کے لیے، میں نے تین معیاری ورچوئل مشینیں شروع کیں - ایک 20 جی بی ہارڈ ڈرائیو، اوبنٹو 18.04۔ 2 ورچوئل CPUs اور 4 گیگس میموری۔

ہم Tarantool انسٹال کرتے ہیں - bash اسکرپٹ چلائیں یا ایک ریپوزٹری شامل کریں اور مناسب طریقے سے Tarantool انسٹال کریں۔ اسکرپٹ سے لنک - (curl -L https://tarantool.io/installer.sh | VER=2.4 sudo -E bash)۔ ہمارے پاس اس طرح کے احکامات ہیں:

tarantoolctl - ٹرانٹولا مثالوں کے انتظام کے لئے مرکزی کمانڈ۔
/etc/tarantool - یہاں پوری ترتیب ہے۔
var/log/tarantool - یہ نوشتہ جات ہیں۔
var/lib/tarantool — ڈیٹا یہاں موجود ہے، اور پھر اسے مثالوں میں تقسیم کیا گیا ہے۔

مثال کے طور پر دستیاب فولڈرز موجود ہیں اور انسٹینس ان ایبل ہیں - اس میں کیا لانچ کیا جائے گا - لوا کوڈ کے ساتھ ایک مثال کنفیگریشن فائل، جس میں یہ بتایا گیا ہے کہ یہ کن بندرگاہوں پر سنتا ہے، اس کے لیے کون سی میموری دستیاب ہے، ونائل انجن کی ترتیبات، کوڈ جو اسٹارٹ اپ پر چلتا ہے۔ سرورز، شارڈنگ، قطاریں، متروک ڈیٹا کو حذف کرنا، وغیرہ۔

مثالیں PostgreS کی طرح کام کرتی ہیں۔ مثال کے طور پر، آپ ایک ڈیٹا بیس کی کئی کاپیاں چلانا چاہتے ہیں جو مختلف پورٹس پر ہینگ ہو۔ یہ پتہ چلتا ہے کہ ایک سرور پر متعدد ڈیٹا بیس مثالیں شروع کی جاتی ہیں، جو مختلف بندرگاہوں پر ہینگ ہوتی ہیں۔ ان میں بالکل مختلف ترتیبات ہوسکتی ہیں - ایک مثال ایک منطق کو نافذ کرتی ہے، دوسری - دوسری۔

مثال کا انتظام

ہمارے پاس tarantoolctl کمانڈ ہے، جو آپ کو Tarantula کے واقعات کو منظم کرنے کی اجازت دیتی ہے۔ مثال کے طور پر، tarantoolctl check example کنفیگریشن فائل کو چیک کرے گا اور کہے گا - اگر وہاں کوئی نحوی غلطیاں نہیں ہیں تو فائل ٹھیک ہے۔

آپ مثال کی حیثیت دیکھ سکتے ہیں - tarantoolctl status example. اسی طرح آپ شروع، بند، دوبارہ شروع کر سکتے ہیں.

مثال کے چلنے کے بعد، آپ اس سے دو طریقوں سے جڑ سکتے ہیں۔

1. انتظامی کنسول

پہلے سے طے شدہ طور پر، Tarantool ایک ساکٹ کھولتا ہے، Tarantool کو کنٹرول کرنے کے لیے عام ASCII متن وہاں بھیجا جاتا ہے۔ کنسول سے کنکشن ہمیشہ ایڈمن صارف کے تحت ہوتا ہے، کوئی توثیق نہیں ہوتی، لہذا ٹرانٹولا کو منظم کرنے کے لیے کنسول پورٹ کو بیرونی بنانے کی ضرورت نہیں ہے۔

اس طریقہ کو استعمال کرتے ہوئے جڑنے کے لیے، آپ کو Tarantoolctl enter instance name درج کرنے کی ضرورت ہے۔ کمانڈ کنسول کو لانچ کرے گی اور ایڈمن صارف کے طور پر جڑے گی۔ کنسول پورٹ کو کبھی بھی باہر کی طرف نہ کھولیں - بہتر ہے کہ اسے یونٹ ساکٹ کے طور پر چھوڑ دیں۔ اس کے بعد صرف وہی لوگ جو ساکٹ پر لکھنے تک رسائی رکھتے ہیں وہ ٹارنٹولا سے جڑ سکیں گے۔

انتظامی چیزوں کے لیے اس طریقہ کی ضرورت ہے۔ ڈیٹا کے ساتھ کام کرنے کے لیے، دوسرا طریقہ استعمال کریں - بائنری پروٹوکول۔

2. کسی مخصوص بندرگاہ سے جڑنے کے لیے بائنری پروٹوکول کا استعمال

کنفیگریشن میں سننے کی ہدایت ہوتی ہے، جو بیرونی مواصلات کے لیے ایک پورٹ کھولتی ہے۔ یہ بندرگاہ بائنری پروٹوکول کے ساتھ استعمال ہوتی ہے اور وہاں تصدیق کو فعال کیا جاتا ہے۔

اس کنکشن کے لیے، tarantoolctl connect to پورٹ نمبر استعمال کیا جاتا ہے۔ اس کا استعمال کرتے ہوئے، آپ ریموٹ سرورز سے جڑ سکتے ہیں، توثیق کا استعمال کر سکتے ہیں اور رسائی کے مختلف حقوق دے سکتے ہیں۔

ڈیٹا ریکارڈنگ اور باکس ماڈیول

چونکہ Tarantool ایک ڈیٹا بیس اور ایپلیکیشن سرور دونوں ہے، اس کے مختلف ماڈیولز ہیں۔ ہم باکس ماڈیول میں دلچسپی رکھتے ہیں - یہ ڈیٹا کے ساتھ کام کرنے کو لاگو کرتا ہے۔ جب آپ باکس میں کچھ لکھتے ہیں، تو Tarantool ڈیٹا کو ڈسک پر لکھتا ہے، اسے میموری میں محفوظ کرتا ہے، یا اس کے ساتھ کچھ اور کرتا ہے۔

ریکارڈ

مثال کے طور پر، ہم باکس ماڈیول میں جاتے ہیں اور box.once فنکشن کو کال کرتے ہیں۔ یہ سرور کے شروع ہونے پر Tarantool کو ہمارا کوڈ چلانے پر مجبور کرے گا۔ ہم ایک جگہ بناتے ہیں جس میں ہمارا ڈیٹا محفوظ کیا جائے گا۔

local function bootstrap()
    local space = box.schema.create_space('example')
    space:create_index('primary')
    box.schema.user.grant('guest', 'read,write,execute', 'universe')

    -- Keep things safe by default
    --  box.schema.user.create('example', { password = 'secret' })
    --  box.schema.user.grant('example', 'replication')
    --  box.schema.user.grant('example', 'read,write,execute', 'space', 'example')
end

اس کے بعد، ہم ایک بنیادی انڈیکس بناتے ہیں - بنیادی - جس کے ذریعے ہم ڈیٹا کو تلاش کر سکتے ہیں۔ پہلے سے طے شدہ طور پر، اگر آپ کسی پیرامیٹرز کی وضاحت نہیں کرتے ہیں، تو ہر ریکارڈ میں پہلا فیلڈ بنیادی انڈیکس کے لیے استعمال کیا جائے گا۔

پھر ہم مہمان صارف کو گرانٹ دیتے ہیں، جس کے تحت ہم بائنری پروٹوکول کے ذریعے جڑتے ہیں۔ ہم پوری مثال میں پڑھنے، لکھنے اور اس پر عمل کرنے کی اجازت دیتے ہیں۔

روایتی ڈیٹا بیس کے مقابلے میں، یہاں سب کچھ بہت آسان ہے۔ ہمارے پاس جگہ ہے - ایک ایسا علاقہ جس میں ہمارا ڈیٹا آسانی سے محفوظ کیا جاتا ہے۔ ہر ریکارڈ کو ٹوپل کہا جاتا ہے۔ یہ MessagePack میں پیک کیا گیا ہے۔ یہ ایک بہت ہی عمدہ فارمیٹ ہے - یہ بائنری ہے اور کم جگہ لیتا ہے - 18 بائٹس بمقابلہ 27۔

Tarantool میں، آپ ایک انتہائی تیز ڈیٹا بیس اور ان کے ساتھ کام کرنے کے لیے ایک ایپلیکیشن کو یکجا کر سکتے ہیں۔ یہاں یہ ہے کہ یہ کرنا کتنا آسان ہے۔

اس کے ساتھ کام کرنا کافی آسان ہے۔ تقریباً ہر لائن، ہر ڈیٹا ریکارڈ میں بالکل مختلف کالم ہو سکتے ہیں۔

ہم Box.space کمانڈ کا استعمال کرتے ہوئے تمام خالی جگہوں کو دیکھ سکتے ہیں۔ کسی مخصوص مثال کو منتخب کرنے کے لیے box.space کی مثال لکھیں اور اس کے بارے میں مکمل معلومات حاصل کریں۔

ٹرانٹول میں دو بلٹ ان انجن ہیں: میموری اور ونائل۔ میموری تمام ڈیٹا کو میموری میں محفوظ کرتی ہے۔ لہذا، سب کچھ آسانی سے اور تیزی سے کام کرتا ہے. ڈیٹا کو ڈسک پر پھینک دیا جاتا ہے، اور آگے لکھنے کا ایک طریقہ کار بھی ہوتا ہے، لہذا اگر سرور کریش ہو جاتا ہے تو ہم کچھ نہیں کھویں گے۔

ونائل ڈسک پر ڈیٹا کو اس شکل میں اسٹور کرتا ہے جو ہم سے زیادہ مانوس ہے - یعنی آپ ہماری میموری سے زیادہ ڈیٹا اسٹور کرسکتے ہیں، اور ٹرانٹولا اسے ڈسک سے پڑھے گا۔

ابھی کے لیے ہم میموری استعمال کریں گے۔

unix/:/var/run/tarantool/example.control> box.space.example
---
- engine: memtx
  before_replace: 'function: 0x41eb02c8'
  on_replace: 'function: 0x41eb0568'
  ck_constraint: []
  field_count: 0
  temporary: false
  index:
    0: &0
      unique: true
      parts:
      - type: unsigned
        is_nullable: false
        fieldno: 1
      id: 0
      space_id: 512
      type: TREE
      name: primary
    primary: *0
  is_local: false
  enabled: true
  name: example
  id: 512
...

unix/:/var/run/tarantool/example.control>

انڈیکس:

کسی بھی جگہ کے لیے ایک بنیادی انڈیکس بنانا ضروری ہے، کیونکہ اس کے بغیر کچھ بھی کام نہیں کرے گا۔ جیسا کہ کسی بھی ڈیٹا بیس میں ہوتا ہے، ہم پہلی فیلڈ - ریکارڈ ID بناتے ہیں۔

حصے:

یہاں ہم اس بات کی نشاندہی کرتے ہیں کہ ہمارا انڈیکس کس چیز پر مشتمل ہے۔ یہ ایک حصے پر مشتمل ہے - پہلا فیلڈ جسے ہم استعمال کریں گے غیر دستخط شدہ قسم کا ہے - ایک مثبت عدد۔ جہاں تک مجھے دستاویزات سے یاد ہے، زیادہ سے زیادہ تعداد 18 کوئنٹلین ہو سکتی ہے۔ یہ بہت ہے.

پھر ہم insert کمانڈ کا استعمال کرتے ہوئے ڈیٹا داخل کر سکتے ہیں۔

unix/:/var/run/tarantool/example.control> box.space.example:insert{1, 'test1', 'test2'}
---
- [1, 'test1', 'test2']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{2, 'test2', 'test3', 'test4'}
---
- [2, 'test2', 'test3', 'test4']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{3, 'test3'}
---
- [3, 'test3']
...

unix/:/var/run/tarantool/example.control> box.space.example:insert{4, 'test4'}
---
- [4, 'test4']
...

unix/:/var/run/tarantool/example.control>

پہلی فیلڈ کو بنیادی کلید کے طور پر استعمال کیا جاتا ہے، اس لیے اسے منفرد ہونا چاہیے۔ ہم کالموں کی تعداد تک محدود نہیں ہیں، اس لیے ہم وہاں جتنا چاہیں ڈیٹا ڈال سکتے ہیں۔ وہ MessagePack فارمیٹ میں بیان کیے گئے ہیں، جسے میں نے اوپر بیان کیا ہے۔

ڈیٹا آؤٹ پٹ

پھر ہم سلیکٹ کمانڈ کا استعمال کرتے ہوئے ڈیٹا کو ڈسپلے کر سکتے ہیں۔

{1} کلید کے ساتھ Box.example.select مطلوبہ اندراج ظاہر کرے گا۔ اگر ہم کلید کو کم کرتے ہیں، تو ہم تمام ریکارڈ دیکھیں گے جو ہمارے پاس ہیں۔ وہ سب کالموں کی تعداد میں مختلف ہیں، لیکن یہاں، اصولی طور پر، کالم کا کوئی تصور نہیں ہے - فیلڈ نمبرز ہیں۔

ڈیٹا کی کوئی بھی مقدار ہو سکتی ہے۔ اور مثال کے طور پر، ہمیں انہیں دوسرے فیلڈ کے ذریعے تلاش کرنے کی ضرورت ہے۔ ایسا کرنے کے لیے، ہم ایک نیا سیکنڈری انڈیکس بناتے ہیں۔


box.space.example:create_index( ‘secondary’, { type = ‘TREE’, unique = false, parts = {{field = 2, type =’string’} }}) 

ہم Create_index کمانڈ استعمال کرتے ہیں۔
آئیے اسے سیکنڈری کہتے ہیں۔

اس کے بعد آپ کو پیرامیٹرز کی وضاحت کرنے کی ضرورت ہے۔ انڈیکس کی قسم TREE ہے۔ یہ منفرد نہیں ہو سکتا، اس لیے Unique = false درج کریں۔

پھر ہم اشارہ کرتے ہیں کہ ہمارا انڈیکس کن حصوں پر مشتمل ہے۔ فیلڈ اس فیلڈ کا نمبر ہے جس سے ہم انڈیکس کو باندھتے ہیں، اور سٹرنگ کی قسم بتاتے ہیں۔ اور اس طرح یہ تخلیق کیا گیا تھا.

unix/:/var/run/tarantool/example.control> box.space.example:create_index('secondary', { type = 'TREE', unique = false, parts = {{field = 2, type = 'string'}}})
---
- unique: false
  parts:
  - type: string
    is_nullable: false
    fieldno: 2
  id: 1
  space_id: 512
  type: TREE
  name: secondary
...

unix/:/var/run/tarantool/example.control>

اب ہم اسے کیسے کہہ سکتے ہیں:

unix/:/var/run/tarantool/example.control> box.space.example.index.secondary:select('test1')
---
- - [1, 'test1', 'test2']
...

تحفظ

اگر ہم مثال کو دوبارہ شروع کریں اور ڈیٹا کو دوبارہ کال کرنے کی کوشش کریں تو ہم دیکھیں گے کہ یہ وہاں نہیں ہے - سب کچھ خالی ہے۔ ایسا اس لیے ہوتا ہے کیونکہ ٹرانٹول چیک پوائنٹ بناتا ہے اور ڈیٹا کو ڈسک میں محفوظ کرتا ہے، لیکن اگر ہم اگلی بچت تک کام کرنا بند کر دیتے ہیں، تو ہم تمام آپریشنز سے محروم ہو جائیں گے - کیونکہ ہم آخری چوکی سے ٹھیک ہو جائیں گے، جو مثال کے طور پر، دو گھنٹے پہلے تھا۔

یہ ہر سیکنڈ کو بچانے کے لیے بھی کام نہیں کرے گا، کیونکہ 20 جی بی کو مسلسل ڈسک پر ڈالنا اچھا خیال نہیں ہے۔

اس مقصد کے لیے رائٹ-ہیڈ لاگ کا تصور ایجاد کیا گیا اور اس پر عمل درآمد کیا گیا۔ اس کی مدد سے، ڈیٹا میں ہر تبدیلی کے لیے، ایک چھوٹی تحریر آگے لاگ فائل میں ایک اندراج بنایا جاتا ہے۔

چوکی تک ہر اندراج ان میں محفوظ ہے۔ ان فائلوں کے لیے ہم سائز سیٹ کرتے ہیں - مثال کے طور پر، 64 MB۔ جب یہ بھر جاتا ہے، ریکارڈنگ دوسری فائل میں جانا شروع ہو جاتی ہے۔ اور دوبارہ شروع ہونے کے بعد، Tarantool کو آخری چیک پوائنٹ سے بحال کر دیا جاتا ہے اور پھر اس کے رک جانے تک بعد کے تمام لین دین کو ختم کر دیا جاتا ہے۔

Tarantool میں، آپ ایک انتہائی تیز ڈیٹا بیس اور ان کے ساتھ کام کرنے کے لیے ایک ایپلیکیشن کو یکجا کر سکتے ہیں۔ یہاں یہ ہے کہ یہ کرنا کتنا آسان ہے۔

اس طرح کی ریکارڈنگ کو انجام دینے کے لیے، آپ کو box.cfg سیٹنگز میں آپشن کی وضاحت کرنے کی ضرورت ہے (مثال کے طور پر.lua فائل میں):

wal_mode = “write”;

ڈیٹا کا استعمال

اب ہم نے جو لکھا ہے اس کے ساتھ، آپ ڈیٹا کو ذخیرہ کرنے کے لیے Tarantula کا استعمال کر سکتے ہیں اور یہ ڈیٹا بیس کے طور پر بہت تیزی سے کام کرے گا۔ اور اب کیک پر آئسنگ وہی ہے جو آپ اس سب کے ساتھ کر سکتے ہیں۔

درخواست لکھنا

مثال کے طور پر، ٹیرانٹولا کے لیے درج ذیل درخواست لکھتے ہیں۔

سپائلر کے نیچے ایپلی کیشن دیکھیں

box.cfg {
    listen = '0.0.0.0:3301';
    io_collect_interval = nil;
    readahead = 16320;
    memtx_memory = 128 * 1024 * 1024; -- 128Mb
    memtx_min_tuple_size = 16;
    memtx_max_tuple_size = 128 * 1024 * 1024; -- 128Mb
    vinyl_memory = 128 * 1024 * 1024; -- 128Mb
    vinyl_cache = 128 * 1024 * 1024; -- 128Mb
    vinyl_max_tuple_size = 128 * 1024 * 1024; -- 128Mb
    vinyl_write_threads = 2;
    wal_mode = "write";
    wal_max_size = 256 * 1024 * 1024;
    checkpoint_interval = 60 * 60; -- one hour
    checkpoint_count = 6;
    force_recovery = true;
    log_level = 5;
    log_nonblock = false;
    too_long_threshold = 0.5;
    read_only   = false
}

local function bootstrap()
    local space = box.schema.create_space('example')
    space:create_index('primary')

    box.schema.user.create('example', { password = 'secret' })
    box.schema.user.grant('example', 'read,write,execute', 'space', 'example')

    box.schema.user.create('repl', { password = 'replication' })
    box.schema.user.grant('repl', 'replication')
end

-- for first run create a space and add set up grants
box.once('replica', bootstrap)

-- enabling console access
console = require('console')
console.listen('127.0.0.1:3302')

-- http config
local charset = {}  do -- [0-9a-zA-Z]
    for c = 48, 57  do table.insert(charset, string.char(c)) end
    for c = 65, 90  do table.insert(charset, string.char(c)) end
    for c = 97, 122 do table.insert(charset, string.char(c)) end
end

local function randomString(length)
    if not length or length <= 0 then return '' end
    math.randomseed(os.clock()^5)
    return randomString(length - 1) .. charset[math.random(1, #charset)]
end

local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')

local httpd = http_server.new('0.0.0.0', 8080, {
    log_requests = true,
    log_errors = true
})

local router = http_router.new()

local function get_count()
 local cnt = box.space.example:len()
 return cnt
end

router:route({method = 'GET', path = '/count'}, function()
    return {status = 200, body = json.encode({count = get_count()})}
end)

router:route({method = 'GET', path = '/token'}, function()
    local token = randomString(32)
    local last = box.space.example:len()
    box.space.example:insert{ last + 1, token }
    return {status = 200, body = json.encode({token = token})}
end)

prometheus = require('prometheus')

fiber = require('fiber')
tokens_count = prometheus.gauge("tarantool_tokens_count",
                              "API Tokens Count")

function monitor_tokens_count()
  while true do
    tokens_count:set(get_count())
    fiber.sleep(5)
  end
end
fiber.create(monitor_tokens_count)

router:route( { method = 'GET', path = '/metrics' }, prometheus.collect_http)

httpd:set_router(router)
httpd:start()

ہم لوا میں کچھ ٹیبل کا اعلان کرتے ہیں جو حروف کی وضاحت کرتا ہے۔ اس پلیٹ کو بے ترتیب تار بنانے کے لیے درکار ہے۔

local charset = {}  do -- [0-9a-zA-Z]
    for c = 48, 57  do table.insert(charset, string.char(c)) end
    for c = 65, 90  do table.insert(charset, string.char(c)) end
    for c = 97, 122 do table.insert(charset, string.char(c)) end
end

اس کے بعد، ہم فنکشن - randomString کا اعلان کرتے ہیں اور قوسین میں لمبائی کی قدر دیتے ہیں۔

local function randomString(length)
    if not length or length <= 0 then return '' end
    math.randomseed(os.clock()^5)
    return randomString(length - 1) .. charset[math.random(1, #charset)]
end

پھر ہم HTTP راؤٹر اور HTTP سرور کو اپنے Tarantula سرور JSON سے جوڑتے ہیں، جسے ہم کلائنٹ کو بھیجیں گے۔

local http_router = require('http.router')
local http_server = require('http.server')
local json = require('json')

اس کے بعد، ہم تمام HTTP سرور انٹرفیس پر پورٹ 8080 پر شروع کرتے ہیں، جو تمام درخواستوں اور غلطیوں کو لاگ ان کرے گا۔

local httpd = http_server.new('0.0.0.0', 8080, {
    log_requests = true,
    log_errors = true
})

اگلا، ہم روٹ کا اعلان کرتے ہیں، تاکہ اگر GET طریقہ کے ساتھ کوئی درخواست پورٹ 8080/count پر آتی ہے، تو ہم ایک لائن سے فنکشن کو کال کرتے ہیں۔ یہ اسٹیٹس کو لوٹاتا ہے - 200، 404، 403 یا کوئی اور جو ہم بیان کرتے ہیں۔

router:route({method = 'GET', path = '/count'}, function()
    return {status = 200, body = json.encode({count = get_count()})}
end)

باڈی میں ہم json.encode واپس کرتے ہیں، اس میں ہم شمار اور getcount کی نشاندہی کرتے ہیں، جسے کہا جاتا ہے اور ہمارے ڈیٹا بیس میں ریکارڈز کی تعداد ظاہر کرتا ہے۔

دوسرا طریقہ

router:route({method = 'GET', path = '/token'}, function() 
    local token = randomString(32) 
    local last = box.space.example:len() 
    box.space.example:insert{ last + 1, token } 
    return {status = 200, body = json.encode({token = token})}
end)

جہاں لائن میں روٹر: روٹ ({طریقہ = 'گیٹ'، راستہ = '/ٹوکن'}، فنکشن () ہم فنکشن کو کال کرتے ہیں اور ایک ٹوکن تیار کرتے ہیں۔

سٹرنگ مقامی ٹوکن = randomString(32) 32 حروف کی بے ترتیب تار ہے۔
لائن میں local last = box.space.example:len() ہم آخری عنصر نکالتے ہیں۔
اور لائن میں box.space.example:insert{ last + 1, token } ہم ڈیٹا کو اپنے ڈیٹا بیس میں لکھتے ہیں، یعنی ہم صرف ID کو 1 تک بڑھاتے ہیں۔ یہ نہ صرف اس اناڑی طریقے سے کیا جا سکتا ہے۔ ٹیرانٹولا میں اس کے سلسلے ہیں۔

ہم وہاں ٹوکن لکھتے ہیں۔

اس طرح، ہم نے درخواست کو ایک فائل میں لکھا۔ آپ وہاں ڈیٹا کو براہ راست جوڑ سکتے ہیں، اور باکس ماڈیول آپ کے لیے تمام گندے کام کرے گا۔

یہ HTTP کو سنتا ہے اور ڈیٹا کے ساتھ کام کرتا ہے، سب کچھ ایک ہی مثال میں ہوتا ہے - ایپلیکیشن اور ڈیٹا دونوں۔ لہذا، سب کچھ بہت تیزی سے ہوتا ہے.

شروع کرنے کے لیے ہم HTTP ماڈیول انسٹال کرتے ہیں:

ہم یہ کیسے کرتے ہیں، بگاڑنے والے کے نیچے دیکھیں

root@test2:/# tarantoolctl rocks install http
Installing http://rocks.tarantool.org/http-scm-1.src.rock
Missing dependencies for http scm-1:
   checks >= 3.0.1 (not installed)

http scm-1 depends on checks >= 3.0.1 (not installed)
Installing http://rocks.tarantool.org/checks-3.0.1-1.rockspec

Cloning into 'checks'...
remote: Enumerating objects: 28, done.
remote: Counting objects: 100% (28/28), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 28 (delta 1), reused 16 (delta 1), pack-reused 0
Receiving objects: 100% (28/28), 12.69 KiB | 12.69 MiB/s, done.
Resolving deltas: 100% (1/1), done.
Note: checking out '580388773ef11085015b5a06fe52d61acf16b201'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

No existing manifest. Attempting to rebuild...
checks 3.0.1-1 is now installed in /.rocks (license: BSD)

-- The C compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found TARANTOOL: /usr/include (found version "2.4.2-80-g18f2bc82d")
-- Tarantool LUADIR is /.rocks/share/tarantool/rocks/http/scm-1/lua
-- Tarantool LIBDIR is /.rocks/share/tarantool/rocks/http/scm-1/lib
-- Configuring done
-- Generating done
CMake Warning:
  Manually-specified variables were not used by the project:

    version


-- Build files have been written to: /tmp/luarocks_http-scm-1-V4P9SM/http/build.luarocks
Scanning dependencies of target httpd
[ 50%] Building C object http/CMakeFiles/httpd.dir/lib.c.o
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:32:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c: In function ‘tpl_term’:
/usr/include/tarantool/lauxlib.h:144:15: warning: this statement may fall through [-Wimplicit-fallthrough=]
    (*(B)->p++ = (char)(c)))
    ~~~~~~~~~~~^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:62:7: note: in expansion of macro ‘luaL_addchar’
       luaL_addchar(b, '\');
       ^~~~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:63:6: note: here
      default:
      ^~~~~~~
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:39:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h: In function ‘tpe_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:147:9: warning: this statement may fall through [-Wimplicit-fallthrough=]
    type = TPE_TEXT;
    ~~~~~^~~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/tpleval.h:149:3: note: here
   case TPE_LINECODE:
   ^~~~
In file included from /tmp/luarocks_http-scm-1-V4P9SM/http/http/lib.c:40:0:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h: In function ‘httpfast_parse’:
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:372:22: warning: this statement may fall through [-Wimplicit-fallthrough=]
                 code = 0;
                 ~~~~~^~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:374:13: note: here
             case status:
             ^~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:393:23: warning: this statement may fall through [-Wimplicit-fallthrough=]
                 state = message;
                 ~~~~~~^~~~~~~~~
/tmp/luarocks_http-scm-1-V4P9SM/http/http/httpfast.h:395:13: note: here
             case message:
             ^~~~
[100%] Linking C shared library lib.so
[100%] Built target httpd
[100%] Built target httpd
Install the project...
-- Install configuration: "Debug"
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/VERSION.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lib/http/lib.so
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/server/tsgi_adapter.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/nginx_server/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/init.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/fs.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/matching.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/middleware.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/request.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/router/response.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/tsgi.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/utils.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/mime_types.lua
-- Installing: /.rocks/share/tarantool/rocks/http/scm-1/lua/http/codes.lua
http scm-1 is now installed in /.rocks (license: BSD)

root@test2:/#

ہمیں چلانے کے لیے پرومیٹیس کی بھی ضرورت ہے:

root@test2:/# tarantoolctl rocks install prometheus
Installing http://rocks.tarantool.org/prometheus-scm-1.rockspec

Cloning into 'prometheus'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 19 (delta 2), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (19/19), 10.73 KiB | 10.73 MiB/s, done.
Resolving deltas: 100% (2/2), done.
prometheus scm-1 is now installed in /.rocks (license: BSD)

root@test2:/#

ہم لانچ کرتے ہیں اور ماڈیول تک رسائی حاصل کر سکتے ہیں۔

root@test2:/# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 Ok
Content-length: 44
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"token":"e2tPq9l5Z3QZrewRf6uuoJUl3lJgSLOI"}

root@test2:/# curl -D - -s http://127.0.0.1:8080/token
HTTP/1.1 200 Ok
Content-length: 44
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"token":"fR5aCA84gj9eZI3gJcV0LEDl9XZAG2Iu"}

root@test2:/# curl -D - -s http://127.0.0.1:8080/count
HTTP/1.1 200 Ok
Content-length: 11
Server: Tarantool http (tarantool v2.4.2-80-g18f2bc82d)
Connection: keep-alive

{"count":2}root@test2:/#

/count ہمیں 200 کا درجہ دیتا ہے۔
/token ٹوکن جاری کرتا ہے اور اس ٹوکن کو ڈیٹا بیس میں لکھتا ہے۔

رفتار کی جانچ

آئیے 50 درخواستوں کے لیے ایک بینچ مارک چلائیں۔ 000 مسابقتی درخواستیں ہوں گی۔

root@test2:/# ab -c 500 -n 50000 http://127.0.0.1:8080/token
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests


Server Software:        Tarantool
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /token
Document Length:        44 bytes

Concurrency Level:      500
Time taken for tests:   14.578 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      7950000 bytes
HTML transferred:       2200000 bytes
Requests per second:    3429.87 [#/sec] (mean)
Time per request:       145.778 [ms] (mean)
Time per request:       0.292 [ms] (mean, across all concurrent requests)
Transfer rate:          532.57 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   10 103.2      0    3048
Processing:    12   69 685.1     15   13538
Waiting:       12   69 685.1     15   13538
Total:         12   78 768.2     15   14573

Percentage of the requests served within a certain time (ms)
  50%     15
  66%     15
  75%     16
  80%     16
  90%     16
  95%     16
  98%     21
  99%     42
 100%  14573 (longest request)
root@test2:/#

ٹوکن جاری کیے جاتے ہیں۔ اور ہم مسلسل ڈیٹا ریکارڈ کر رہے ہیں۔ 99% درخواستوں پر 42 ملی سیکنڈ میں کارروائی کی گئی۔ اس کے مطابق، ہمارے پاس 3500 کور اور 2 گیگا بائٹس میموری والی ایک چھوٹی مشین پر فی سیکنڈ تقریباً 4 درخواستیں ہیں۔

آپ کچھ 50000 ٹوکن بھی منتخب کر سکتے ہیں اور اس کی قیمت دیکھ سکتے ہیں۔

آپ نہ صرف HTTP استعمال کرسکتے ہیں، بلکہ بیک گراؤنڈ فنکشنز بھی چلا سکتے ہیں جو آپ کے ڈیٹا پر کارروائی کرتے ہیں۔ اس کے علاوہ مختلف محرکات ہیں۔ مثال کے طور پر، آپ اپ ڈیٹس پر فنکشنز کو کال کر سکتے ہیں، کچھ چیک کر سکتے ہیں - تنازعات کو درست کریں۔

آپ اسکرپٹ ایپلی کیشنز کو براہ راست ڈیٹا بیس سرور میں لکھ سکتے ہیں، اور کسی بھی چیز سے محدود نہیں، کسی بھی ماڈیول کو جوڑ سکتے ہیں اور کسی بھی منطق کو لاگو کرسکتے ہیں۔

ایپلیکیشن سرور بیرونی سرورز تک رسائی حاصل کرسکتا ہے، ڈیٹا بازیافت کرسکتا ہے اور اسے اپنے ڈیٹا بیس میں شامل کرسکتا ہے۔ اس ڈیٹا بیس کا ڈیٹا دیگر ایپلیکیشنز استعمال کرے گا۔

ٹارنٹولا یہ خود کرے گا، اور آپ کو الگ درخواست لکھنے کی ضرورت نہیں ہوگی۔

آخر میں

یہ ایک بڑے کام کا صرف پہلا حصہ ہے۔ دوسرا بہت جلد Mail.ru گروپ کے بلاگ پر شائع کیا جائے گا، اور ہم اس مواد میں اس کا لنک ضرور شامل کریں گے۔

اگر آپ ان پروگراموں میں شرکت کرنے میں دلچسپی رکھتے ہیں جہاں ہم یہ چیزیں آن لائن بناتے ہیں اور حقیقی وقت میں سوالات پوچھتے ہیں، تو رابطہ کریں۔ REBRAIN کے ذریعے چینل DevOps.

اگر آپ کو کلاؤڈ پر جانے کی ضرورت ہے یا آپ کے بنیادی ڈھانچے کے بارے میں سوالات ہیں، ایک درخواست چھوڑنے کے لئے آزاد محسوس کریں.

PS ہمارے پاس ہر ماہ 2 مفت آڈٹ ہوتے ہیں، شاید آپ کا پروجیکٹ ان میں سے ایک ہو۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں