از یک gateway برای تجمیع چندین request منحصربهفرد در یک request استفاده کنید. این الگو زمانی مفید است که یک کلاینت برای انجام یک عملیات باید چندین تماس با سیستمهای backend مختلف برقرار کند.
برای انجام یک تسک واحد، یک کلاینت ممکن است مجبور باشد چندین فراخوانی با سرویسهای مختلف backend برقرار کند. برنامهای که برای انجام یک تسک به سرویسهای زیادی متکی است، پس باید منابع را برای هر request مصرف کند. هنگامی که هر ویژگی یا سرویس جدیدی به برنامه اضافه میشود، درخواستهای اضافی موردنیاز است که نیاز به مصرف بیشتر منابع و فراخوانیهای شبکه را بیشتر میکند. این ارتباط بین یک client و یک backend میتواند بر کارایی و مقیاسپذیری برنامه تأثیر منفی بگذارد. معماریهای میکروسرویس این مشکل را رایجتر کردهاند، زیرا اپلیکیشنهای ساختهشده پیرامون بسیاری از سرویسهای کوچکتر، تعداد فراخوانی متقابل سرویس بیشتری دارند.
در نمودار زیر client برای هر سرویس request ارسال میکند (۱،۲،۳). هر سرویس request را پردازش میکند و پاسخ را به برنامه برمیگرداند (۴،۵،۶). در یک شبکه سلولی با تأخیر زمانی معمولاً بالا، استفاده از requestهای مستقل به این شیوه ناکارآمد است و میتواند منجر به قطع اتصال یا requestهایی ناقص شود. درحالیکه هر requestهای ممکن است بهصورت موازی انجام شود، برنامه باید دادهها را برای هر request ارسال و سپس صبر کند و در نهایت پردازش کند و چون همهی در اتصالات و ارتباطات جداگانه و مجزا است احتمال خطا و شکست را افزایش میدهد.
از یک gateway برای کاهش تماسها و ارتباطها بین client و serviceها استفاده کنید. gateway همیشه requestهای client را دریافت میکند، requestها را به سیستمهای backend مختلف ارسال(dispatche) میکند و سپس نتایج را جمعآوری میکند و آنها را برای client درخواستکننده ارسال میکند.
این الگو میتواند تعداد requestهایی را که برنامه برای سرویس backend ارائه میکند کاهش دهد و عملکرد برنامه را در شبکههای با high-latency بهبود بخشد.
در نمودار زیر اپلیکیشن درخواستی را به gateway (1) ارسال میکند. request شامل بستهای از requestهای اضافی است. gateway اینها را تجزیهوتحلیل میکند و هر درخواست را با ارسال آن به سرویس مربوطه پردازش میکند (۲). هر سرویس یک پاسخ به gateway (3) برمیگرداند. gateway پاسخهای هر سرویس را ترکیب میکند و پاسخ را به برنامه میفرستد (۴). برنامه تنها یک request میدهد و تنها یک پاسخ از gateway دریافت میکند.
- بههیچوجه gateway نباید با سرویس backend بهعنوان سرویس متصل شده میانی ارتباط داشته باشد.
- همیشه gateway باید در نزدیکی سرویسهای backend قرار گیرد تا تأخیر زمانی تاحدامکان کاهش یابد.
- سرویس gateway ممکن است به یک نقطه شکست و خرابی تبدیل شود. اطمینان حاصل کنید که gateway بهدرستی طراحی شده است تا نیازهای دردسترسبودن برنامه شما را برآورده کند.
- ممکن است gateway یک گلوگاه ایجاد کند. اطمینان حاصل کنید که دروازه عملکرد مناسبی برای تحمل load دارد و میتواند برای برآوردهکردن رشد و توسعه پیشبینیشده شما جهت توسعه نرمافزار مقیاسدهی(scale) شود.
- تست مقیاسدهی را در برابر gateway انجام دهید تا مطمئن شوید که خرابیهای متوالی و دنبالهدار برای سرویسها ایجاد نمیکنید.
- با استفاده از تکنیکهایی مانند bulkheads, circuit breaking, retryو timeout ها، نرمافزاری با انعطافپذیری بالا را اجرا کنید.
- اگر یک یا چند فراخوانی از سرویس بیش از حد طول بکشد، ممکن است زمان سپری شده و بازگرداندن مجموعهای تا حدی قابلقبول باشد. در نظر بگیرید که برنامه شما چگونه با این سناریو برخورد خواهد کرد.
- از ورودی/خروجی ناهمزمان (asynchronous I/O) استفاده کنید تا اطمینان حاصل کنید که تأخیر در backend باعث مشکلات عملکرد در برنامه نمیشود.
- پیادهسازی یک ردیاب (tracing) توزیع شده با استفاده از شناسههای(IDs) منحصربهفرد برای ردیابیکردن هر فراخوانی جداگانه.
- متریکهای request و اندازه response را نظارت و مانیتور کنید.
- بازگرداندن دادههای cache را بهعنوان یک راهبُرد شناسایی شکست برای مدیریت شکست و خطاهای درخواستهای ارتباطی در نظر بگیرید.
- بهجای ایجاد تجمیع (aggregation) در gateway، قراردادن یک سرویس مجتمع در پشت gateway را در نظر بگیرید. Requestهای تجمیع شده احتمالاً نیازمند منابع متفاوتی نسبت به سایر سرویسها در gateway خواهد بود و ممکن است بر عملکرد مسیریابی و بارگذاری روی gateway تأثیر بگذارد.
از این الگو زمانی استفاده کنید که:
- یک کلاینت برای انجام یک عملیات باید با چندین سرویس backend ارتباط برقرار کند.
- کلاینت ممکن است از شبکههایی با تأخیر زمانی قابلتوجه مانند شبکههای سلولی استفاده کند.
این الگو ممکن است زمانی مناسب نباشد که:
- زمانی که میخواهید تعداد فراخوانیهای بین یک کلاینت و یک سرویس را در چندین عملیات کاهش دهید. در آن سناریو، ممکن است بهتر باشد یک عملیات دستهای/گروهی به سرویس اضافه شود.
- کلاینت یا برنامه در نزدیکی سرویس backend قرار دارد و تأخیر عامل مهمی نیست.
مثال زیر نحوه ایجاد یک سرویس NGINX تجمیع شده در یک gateway ساده با استفاده از زبان برنامهنویسی Lua را نشان میدهد.
worker_processes 4;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location = /batch {
content_by_lua '
ngx.req.read_body()
-- read json body content
local cjson = require "cjson"
local batch = cjson.decode(ngx.req.get_body_data())["batch"]
-- create capture_multi table
local requests = {}
for i, item in ipairs(batch) do
table.insert(requests, {item.relative_url, { method = ngx.HTTP_GET}})
end
-- execute batch requests in parallel
local results = {}
local resps = { ngx.location.capture_multi(requests) }
for i, res in ipairs(resps) do
table.insert(results, {status = res.status, body = cjson.decode(res.body), header = res.header})
end
ngx.say(cjson.encode({results = results}))
';
}
location = /service1 {
default_type application/json;
echo '{"attr1":"val1"}';
}
location = /service2 {
default_type application/json;
echo '{"attr2":"val2"}';
}
}
}