Skip to content

کنسول SQL ​

کوئری‌گرفتن از همهٔ صف‌های یک کلاستر در کنسول SQL و سپس دنبال‌کردن tail زنده

پرسشی که یک اپراتور واقعاً با آن می‌آید این است: «سفارش ۴۴۷۱ کجا رفت؟». آرتمیس نمی‌تواند پاسخش را بدهد. تنها فیلتر سمت سرورش JMS selector است که هدرها و ویژگی‌های اپلیکیشن را می‌بیند — نه بدنه را — و هر بار روی یک صف در یک نود اعمال می‌شود.

کنسول SQL پاسخش را می‌دهد، روی همهٔ صف‌های کلاستر، در یک کوئری.

sql
SELECT * FROM "ORDER.*"
WHERE body->>'orderId' = '4471'
LIMIT 50

یک گویش واقعی، زیرمجموعه‌ای کوچک ​

فقط SELECT. یک FROM. WHERE، ORDER BY، LIMIT. بدون join، بدون subquery، بدون union، بدون CTE — و هیچ تغییری اصلاً قابل بیان نیست.

نحو، عمداً SQL واقعی است تا گرامر، رنگ‌آمیزی و تکمیل آمادهٔ ادیتور بدون تغییر کار کنند. کوئری‌ها به AST تجزیه و گره‌به‌گره در برابر یک کاتالوگ ستون ثابت اعتبارسنجی می‌شوند، با ردِ پیش‌فرض. هیچ‌چیز با تطبیق الگو روی متن کوئری اعتبارسنجی نمی‌شود؛ یک عبارت باقاعده که نبودِ DROP را ادعا کند، همان روشی است که این کار معمولاً با آن اشتباه انجام می‌شود.

نام صف‌ها همیشه داخل گیومهٔ دوتایی می‌آیند — ORDER.IN هم واژهٔ رزرو است و هم نقطه دارد — و wildcardها از آنِ آرتمیس‌اند نه SQL: * یک سطحِ نقطه‌جدا و # چند سطح را می‌گیرد.

کوئری از کجا می‌خواند ​

پیشوند schema، backend را در خودِ متن کوئری انتخاب می‌کند؛ پس کوئری‌ای که در یک تیکت paste می‌شود همچنان می‌گوید از کجا خوانده است.

FROM broker."Q"بروکرهای زنده. حقیقتِ اکنون.
FROM index."Q"ایندکس تاریخی — هنوز پیام‌هایی را دارد که از آن پس مصرف شده‌اند، و فقط صف‌هایی را پوشش می‌دهد که برایشان اشتراک گرفته‌اید.
FROM "Q"planner انتخاب می‌کند و plan می‌گوید کدام را برداشته است.

هزینهٔ یک predicate — پیش از اجرا ​

این بخشی است که ارزش دانستن دارد. هر جزء AND در سطح بالا طبقه‌بندی می‌شود:

ردهمعنا
Targetانتخاب می‌کند کدام صف‌ها خوانده شوند. هزینه‌ای ندارد.
Pushdownبه یک JMS selector تبدیل می‌شود، پس بروکر فیلتر می‌کند و Rahdar پیام‌های نامنطبق را اصلاً نمی‌بیند. هزینه‌ای ندارد.
ScanRahdar باید هر پیامی را که بروکر برگردانده بررسی کند.

هدرها و ویژگی‌های اپلیکیشن pushdown می‌شوند. بدنه هرگز نمی‌تواند — جز Rahdar هیچ‌چیز نمی‌تواند آن را بخواند. خط هزینه زیر ادیتور پیش از اجرا در یک جمله می‌گوید کوئری شما کدام‌یک است (فیلتر broker، scan، ایندکس، بدون هزینه)، و وقتی برآورد ممکن نیست «در دسترس نیست» و دلیلش را می‌نویسد و هرگز آن را صفر نشان نمی‌دهد؛ و بالاتر از سقف هزینهٔ پیکربندی‌شده، کوئری همراه با برآورد، سقف، و راهنمایی برای باریک‌ترکردن آن رد می‌شود. رد می‌شود و بریده نمی‌شود: نتیجهٔ بریده‌شده در یک نگاه از نتیجهٔ کامل قابل تشخیص نیست، و اپراتوری در میانهٔ یک حادثه آن را «نیست» می‌خواند.

یک تلهٔ گفتنی

predicate ای که به‌تنهایی رایگان است، درون یک OR کنار یک predicate روی بدنه دیگر رایگان نیست. pushdown کردن یک طرف OR مجموعه‌ای را که طرف دیگر می‌بیند باریک می‌کند — پس یک عبارت فصلی که شامل یک scan باشد، در کل scan می‌شود. این تنها اشتباه این حوزه است که به‌جای پاسخ کند، پاسخ بی‌صدا نادرست می‌دهد.

نوشتن، اجرا و لغو ​

ادیتور و نتایج در یک فضای کار قرار دارند. جداکننده‌ی میان آن‌ها را بکشید، یا روی آن فوکوس کنید و ↑ یا ↓ بزنید (هر گام ۵٪، با Shift ده درصد)، و با Home و End کوچک‌ترین و بزرگ‌ترین ادیتور را بگیرید. کوچک‌ترین ادیتور هم سه خط و خط هزینه‌ی زیر آن را نشان می‌دهد. Rahdar این تقسیم را در همین مرورگر به خاطر می‌سپارد.

اجرا و لغو کنار هم در نوار ابزار Query بالای فضای کار هستند، پس هر قدر هم ادیتور کوچک باشد دیده می‌شوند. Ctrl . (روی مک ⌘ .) از داخل ادیتور یا هرجای صفحه لغو می‌کند. لغو، stream را می‌بندد؛ همین کوئری را در سرور آزاد می‌کند و هر خواندن broker را متوقف می‌کند. ردیف‌هایی که رسیده‌اند روی صفحه می‌مانند و کنسول می‌گوید کوئری لغو شده و این ردیف‌ها پاسخ کامل نیستند. لغو یک tail زنده فقط آن را متوقف می‌کند. Escape هرگز لغو نمی‌کند: به ترتیب تکمیل را می‌بندد، انتخاب را جمع می‌کند، و سپس فوکوس را از ادیتور به نوار ابزار Query می‌برد.

خطای نحوی روی توکن خطادار در ادیتور علامت می‌خورد و دلیلش کنار آن و در خط هزینه آمده است. F8 به آن می‌رود و Ctrl Shift M تشخیص‌ها را فهرست می‌کند. کوئری ردشده یا ناموفق به‌صورت یک خطا با علت و گام بعدی نشان داده می‌شود و رد شدن، برآورد و سقفی را که بر پایه‌ی آن رد شده همراه دارد.

نتایج از همان جدولی استفاده می‌کنند که هر نمای دیگر دارد. منوی ستون‌ها ستونی را نشان یا پنهان می‌کند و با دکمه‌های «انتقال به قبل» و «انتقال به بعد» جابه‌جایش می‌کند و انتخاب را در همین مرورگر نگه می‌دارد. پیام، که ردیف را مشخص می‌کند، همیشه اول می‌ماند.

ستون‌ها ​

سازگار با selector (رایگان): priority، durable، timestamp، expiration، size، jmsType، correlationId، groupId، userId، و هر ویژگی اپلیکیشن به‌صورت props.<name>.

Target (رایگان): queue، address، node.

Scan: body، messageId، messageType، replyTo، و — فقط روی ایندکس — observedAt و lastSeenAt.

یک فیلد JSON درون بدنه به‌صورت body->>'orderId' نوشته می‌شود. تنها توابعی که گویش می‌پذیرد now()، lower() و upper() هستند، به‌علاوهٔ interval در زمان نسبی. زمان نسبی از طریق اختلاف ساعتِ اندازه‌گیری‌شدهٔ هر نود نرمال‌سازی می‌شود، پس بروکری با ساعت منحرف هم درست پاسخ می‌دهد.

نمونه‌ها ​

sql
-- ارزان‌ترین حالت: بدون هیچ predicate، بروکر صفحه‌های ابتدایی‌اش را برمی‌گرداند.
SELECT * FROM "ORDER.IN" ORDER BY timestamp DESC LIMIT 100;

-- هر دو predicate به یک selector روی یک wildcard تبدیل می‌شوند. هنوز رایگان.
SELECT * FROM "ORDER.*" WHERE priority > 4 AND durable = true LIMIT 200;

-- ویژگی‌های اپلیکیشن هم سازگار با selector هستند.
SELECT * FROM "ORDER.IN" WHERE props.tenant = 'acme' LIMIT 200;

-- یک scan. اول با یک predicate روی هدر باریکش کنید.
SELECT * FROM "ORDER.IN" WHERE body LIKE '%4471%' LIMIT 50;

-- یک پنجرهٔ زمانی، کوانتیده و تصحیح‌شده برای انحراف ساعت.
SELECT * FROM "ORDER.*"
WHERE timestamp > now() - interval '2 hours'
ORDER BY timestamp DESC LIMIT 500;

ایندکس اختیاری ​

ایندکس پیام به‌ازای هر صف انتخابی، محدود به دورهٔ نگهداری، و دورانداختنی است. وجود دارد تا بتوان دربارهٔ پیامی پرسید که پیشتر مصرف شده — چیزی که بروکرها، به‌درستی، دیگر هیچ نمی‌دانند. از نظر کنترل دسترسی و حذف، همچون payload نگه‌داشته‌شده با آن رفتار می‌شود، و انداختنش تاریخچه را می‌گیرد نه حقیقت را.

نمایه به دو شکل پر می‌شود و ادعای این دو یکی نیست:

حالتیک ردیف یعنی چه
نمونه‌برداری‌شدهیک نظرسنجی روی این صف این پیام را دیده است. پیامی که میان دو نظرسنجی رسید و مصرف شد هرگز ثبت نشد.
ضبط‌شدهاین address این پیام را مسیریابی کرد. اینکه در این میان چیزی آن را مصرف کرده یا نه فرقی نمی‌کند.

ضبط مسیریابی بروکرها را تغییر می‌دهد، پس کنشی صریح با دسترسی جداگانهٔ خودش است و صفحهٔ خودش را دارد: ضبط پیام.

tail زنده ​

tail یک poll است، هرگز یک consume نیست. نمی‌تواند چیزی را تغییر دهد و با مصرف‌کننده‌های شما رقابت نمی‌کند. رابط کاربری این را به‌طور دائمی اعلام می‌کند، چون یک tail نمونه‌ای که مثل ضبط کامل خوانده شود، راهی است برای رسیدن به این نتیجهٔ نادرست که پیامی هرگز ارسال نشده است.

اقدام روی یک نتیجه ​

نمی‌توانید. عمداً. اقدام روی یک سطر نتیجه از مسیر عملیات عادی پیام می‌گذرد که از پیش dry run، سقف انبوه و رکورد ممیزی را دارد — مسیر دومی به سمت یک فعل مخرب، جای دومی برای اشتباه‌کردن در قرارداد ایمنی است.

تصمیم‌ها (انگلیسی) ​

Apache-2.0. Apache ActiveMQ and Apache ActiveMQ Artemis are trademarks of the Apache Software Foundation. Rahdar is an independent project, not produced by, endorsed by, or affiliated with the ASF.