EventBus Mesh – انجمن DEV

اخیراً هنگام آوردن EventBus EventBridge به برخی از برنامه ها، به این موضوع بسیار فکر کرده ام. در مورد پروژههای فعلی که با کدهای موجود روی آنها کار میکنم، 100 بار گفتهام، اگر EventBridge در هنگام شروع آنها وجود داشت، من آنقدر کد مبتنی بر SNS->SQS نداشتم. اما وقتی در فناوری در حال توسعه کار می کنید، زندگی چنین است. وارد EventBus Mesh شوید
اقلام میکروسرویس متعلق به مالکیت
من می خواهم با این ایده شروع کنم که در معماری Microservice دوست دارم همه چیز تا حد امکان مستقل باشد. این بدان معناست که اقلام زیر هر کدام متعلق به خود مرز هستند
- تعریف API
- مدل داده و ذخیره داده
- کد Frontend و Backend
- هر گونه کانال ارتباطی ناهمگام
- راهی برای انتشار که فقط از آن مرز استفاده کنید
- راهی برای اشتراک که فقط آن مرز می تواند از آن استفاده کند
Pub/Sub قبل از EventBridge
قبل از EventBridge، نرم افزارهای زیادی ساختم که شبیه شکل زیر بود. و برای وضوح، وجود دارد 100% هیچ اشکالی در این روش وجود ندارد
- عملکردهای پشت دروازه API
- یک یا چند جدول DynamoDB تحت کنترل آن
- SQS برای اشتراک در سایر موضوعات SNS (فقط می تواند از آن بخواند)
- موضوع SNS برای انتشار پیام ها/رویدادها در اکوسیستم. فقط می تواند در آن موضوع منتشر کند
با ظهور EventBridge Pipes و توانایی EventBridge Rules برای راهاندازی یک تابع Step (مانند این الگوی EventBridge Step Function Rule)، نیاز به بررسی جایگزینی SNS/SQS با EventBridge برای ویژگیها و پروژههای جدید احساس کردم.
باز هم، هیچ مشکلی با هیچ یک از موارد بالا وجود ندارد، اما من می خواستم برخی از قابلیت های اضافی را به دست بیاورم
مزایای انتقال به EventBridge
- قوانین – آنها بیانگرتر و قدرتمندتر از فیلتر کردن پیام SNS ساده هستند. فیلتر کردن باعث صرفه جویی در چرخه های اجرایی می شود که باعث صرفه جویی در هزینه و صرفه جویی در ضایعات می شود
- Schema Discovery – ویژگی بسیار خوبی برای بیان پیام ها/رویدادها از طریق Schema
- لوله ها – مستقل هستند، آنها برای فیلتر کردن، غنی سازی و تبدیل فوق العاده هستند. برای اطلاعات بیشتر در مورد Pipes، اینجا را بخوانید
فقط با این سه مزیت، من در اجرای بیهوده صرفه جویی می کنم، نقاط خرابی را حذف می کنم و Lambdas و سایر کدهایی که می توانند خطاهایی را که باید آزمایش شوند را حذف می کنم. این مقاله قدیمی توسط جف بار که به توصیف کلیدی معروفی میپردازد که جف بزوس در جایی که در مورد “بلند کردن غیرمتمایز سنگین سنگین” صحبت میکند، مثالی است که چرا من دوست دارم این نوع کد را به سمت ابر هدایت کنم.
EventBus Mesh چیست
من این نمودار ساده را ترسیم کردم تا نحوه چیدمان اتوبوس ها را برجسته کنم.
برخی از قطعات اصلی این الگو این است
- توابع به درخواست های API پاسخ می دهند
- توابع (Lambda یا Step) با DynamoDB تعامل دارند
- EventBridge تبدیل به چسب می شود
- سرویس A Bus به سرویس B Bus متصل می شود
- سرویس A Bus به توابع در سرویس A متصل می شود
- EventBridge Pipe برای اتصال به DynamoDB در سرویس A استفاده می شود و سپس در سرویس A Bus ثبت می شود.
چیزی که واقعاً مهم است، “مرزها” هستند. مهم است که مطمئن شویم آنچه که متعلق به آن مرز است جدا شده است. چسب واقعی اتوبوس -> اتوبوس است. این مانند Pub/Sub است (و همینطور است) اما به جای اشتراک یک SQS Queue در یک موضوع SNS، سرویس B’s Bus را در bus Service A مشترک می کنید. علاوه بر این، مطمئن شوید که قوانین مربوط به داده هایی را که آن اتوبوس ها را به یکدیگر متصل می کند، مشخص کنید.
مشکل بزرگ برای من این است که اتوبوس B هنگامی که به اتوبوس A متصل می شود، در مورد اتوبوس A می داند. و در موردی که همه اینها داخلی یک مجموعه از محصولات است، من را آزار نمی دهد، بنابراین امیدوارم که شما را ناراحت نکند.
راه اندازی دو اتوبوس
برای این مثال، قصد داریم دو EventBuse بسازیم و آنها را به هم وصل کنیم. بسیار شبیه به نمودار بالا.
بیایید به چند کد CDK برای ساخت نگاه کنیم
EventBus One
export class EventBusOne extends Construct {
private readonly _bus: EventBus;
constructor(scope: Construct, id: string) {
super(scope, id);
this._bus = new events.EventBus(scope, "EventBusOne", {
eventBusName: "event-bus-one",
});
}
get eventBus(): EventBus {
return this._bus;
}
}
EventBus Two
export class EventBusTwo extends Construct {
private readonly _bus: EventBus;
constructor(scope: Construct, id: string) {
super(scope, id);
this._bus = new events.EventBus(scope, "EventBusTwo", {
eventBusName: "event-bus-two",
});
}
get eventBus(): EventBus {
return this._bus;
}
}
هنگامی که اجرا می شود، منابع ایجاد شده در کنسول به این صورت خواهند بود.
با پایه دو EventBuse، اجازه دهید نگاهی به اتصال آنها به یکدیگر بیندازیم.
مش EventBus را با یک قانون ایجاد کنید
برای این مثال، بیایید فرض کنیم که Bus2 به رویدادهایی علاقه مند است که در اتوبوس یکی فرود می آیند که دارای detail-type
از “اتوبوسینگ”. با CDK و TypeScript این کار را با این کد انجام می دهیم.
private buildBusOneRule = (
scope: Construct,
props: EventBridgeRuleStackProps
) => {
const rule = new Rule(this, "BusOne-BusTwo-Rule", {
eventPattern: {
detailType: ["Busing"],
},
ruleName: "bus-two-mesh",
eventBus: props.busOne,
});
const dlq = new Queue(this, "BusOneBusTwoMesh-DLQ");
const role = new Role(this, "BusOneBusTwoMesh-Role", {
assumedBy: new ServicePrincipal("events.amazonaws.com"),
});
rule.addTarget(
new targets.EventBus(props.busTwo, {
deadLetterQueue: dlq,
role: role,
})
);
};
هنگام اتصال اتوبوس ها به یکدیگر، خروجی آن مانند شکل زیر در کنسول خواهد بود.
من دوست دارم از قرارداد نامگذاری “مش” در نام استفاده کنم فقط به این دلیل که قوانین مربوط به اتصال اتوبوس ها را به راحتی مشخص کنم. و آنها را می توان بر روی آن کلمه کلیدی جستجو کرد.
قوانین BusTwo برای تحریک اهداف
اکنون که BusTwo رویدادها را با detail-type
از “اتوبوس”، منطقی است که آن رویداد به جایی برود. در یک سناریوی واقعی، من ممکن است به تغییر در یک سیستم پاسخ دهم و نیاز به مدیریت آن تغییر در سیستم دیگر داشته باشم. با استفاده از EventBus و Rules میتوانید واقعاً دقیق شوید. برای مثال
- فقط رویدادهایی که دارای خاصیت خاصی هستند
detail-type
به یک ماشین دولتی خاص بروید - به دنبال چندگانه باشید
detal-type
که به همان State Machine می روند - به دنبال موارد منطبق در خود محموله باشید
- بسیاری از گزینه های دیگر که در اینجا قابل بررسی است
چیزها واقعاً به خوبی مقیاس می شوند و می توانند به میل واقعی شما گسترش یابند.
private buildBusTwoRule = (
scope: Construct,
props: EventBridgeRuleStackProps
) => {
const rule = new Rule(this, "SampleEventSM-Rule", {
eventPattern: {
detailType: ["Busing"],
},
ruleName: "bus-two-busing",
eventBus: props.busTwo,
});
const dlq = new Queue(this, "SampleEventSM-DLQ");
const role = new Role(this, "SampleEventSM-Role", {
assumedBy: new ServicePrincipal("events.amazonaws.com"),
});
rule.addTarget(
new targets.SfnStateMachine(props.stateMachine, {
input: RuleTargetInput,
deadLetterQueue: dlq,
role: role,
})
);
};
کد بالا باید شباهت زیادی به کدی داشته باشد که EventBuses را به هم متصل می کند، اما هدف Rule اکنون StateMachine است و نه EventBus دیگری.
هنگامی که اجرا می شود و تا Cloud مستقر می شود، کنسول به شما نشان می دهد که قانون به این صورت ارائه می شود.
الگوی رویداد قانون
هدف قانون
اجرای هدف EventBus Mesh
تمام هدف اتصال دو یا چند اتوبوس به هم این است که مصرف کننده یکی از اتوبوس ها بتواند با اطلاعات به روز شده یا دستوری که روی سیم گذاشته شده کاری انجام دهد.
در مورد این نمایش، من قصد دارم از توابع Step با یک ماشین حالت ساده استفاده کنم. با نگاهی سریع به آنچه مستقر شده است، خواهید دید که این یک مرحله است. مطمئناً اگر این رویداد را مدیریت کنید، چیز قویتری میخواهید، اما این فقط یک نسخه نمایشی است و این مقاله در توابع مرحله نیست.
/**
* Sets up the state machine. Brings in the roles, permissions and appropriate keys and whatnot
* to allow the state machine to do its thing
*
* @param {Construct} scope - the context for the state machine
*/
finalizeStateMachine = (scope: Construct) => {
const logGroup = new logs.LogGroup(this, "CloudwatchLogs", {
logGroupName: "/aws/vendedlogs/states/sample-state-machine",
});
const role = new Role(this, "StateMachineRole", {
assumedBy: new ServicePrincipal("states.us-west-2.amazonaws.com"),
});
const flow = this.buildStateMachine(scope);
this._stateMachine = new stepfunctions.StateMachine(this, "StateMachine", {
role: role,
stateMachineName: "SampleStateMachine",
definition: flow,
stateMachineType: stepfunctions.StateMachineType.EXPRESS,
timeout: Duration.seconds(5),
logs: {
level: LogLevel.ALL,
destination: logGroup,
includeExecutionData: true,
},
});
};
/**
* Creates the workflow for the state machine. Builds transitions and errors/catches/retries
*
* @param {Construct} scope - the context for the state machine
*/
buildStateMachine = (scope: Construct): stepfunctions.IChainable => {
return new Succeed(scope, "We made it and it finished");
};
بسته شدن
امیدواریم که لمسی از قدرت این الگو را دیده باشید. با استفاده از EventBus Mesh شما توانایی اتصال چندین ویژگی را با هم به دست می آورید و سپس انزوا و کنترل انتشار و خواندن آن رویدادها را به دست می آورید و همچنین از Pipes برای کمک به فیلتر، غنی سازی و تغییر در صورت نیاز استفاده می کنید.
در اکثر موارد بدون سرور و AWS راههای مختلفی برای حل مشکلات وجود دارد، اما استفاده از EventBridge Meshes باید الگوی جدیدی باشد که اکنون میتوانید آن را در جعبه ابزار خود معرفی کنید.
و مثل همیشه، اگر میخواهید این کد را در عمل ببینید، با خیال راحت آن را از مخزن Github پایین بکشید. سپس می توانید بدوید
محیط را آماده کنید
npm install
استقرار EventBus Mesh
cdk deploy
EventBus Mesh را نابود کنید
cdk destroy
ساختمان مبارک!