ادعایی که بررسی میشود
این مقاله استدلال میکند که چارچوببندی درست، تقویت اثر است نه نوآوری، و پاسخ درست کنترل مرزی است نه جایگزینی املاک. بازنویسی یک برنامه چندساله است؛ ریسک تقویت اثر همین فصل جاری وجود دارد. کنترلهای مرزی ارزان، قابل آزمون و برگشتپذیر هستند و همچنین آسیب ناشی از اتوماسیون معمولی بدتنظیم را کاهش میدهند — که در عمل منبعی بسیار شایعتر از آسیب است تا یک دشمن عمدی.
تقویت اثر، نه نوآوری
یک مهاجم انسانی محدود به توجه است. یک نفر میتواند چند فرضیه را در ذهن نگه دارد، با سرعتی محدود تایپ کند و با هزینهای جابهجایی زمینه انجام دهد. یک ازدحام عامل محدود به بودجه و محدودیتهای نرخ است. اگر هیچکدام وجود نداشته باشد، ازدحام تا هر اندازهای که هدف بپذیرد گسترش مییابد. گلوگاه از شناخت مهاجم به تحمل هدف منتقل میشود.
این جابهجایی بیشتر جایی اهمیت دارد که یک رابط قدیمی فاقد سه ویژگی مشخص باشد:
- محدودیت نرخ. بدون بودجه درخواست بهازای هر principal، یک عامل میتواند یک endpoint را تا یافتن حالت مرزی کاوش کند. این فقدان یک حفره جدید نیست؛ یک حفره قدیمی است که پیشتر عبور از آن پرهزینه بود.
- کلیدهای idempotency. یک مسیر نوشتن که نمیتواند بازتلاش را از قصد جدید تشخیص دهد، تحت فشار بازتلاش رکوردهای تکراری تولید میکند. عاملها بهشدت بازتلاش میکنند چون بازتلاش برایشان ارزان است.
- ردپای حسابرسی. اگر یک فراخوانی به یک principal قابل انتساب نباشد، اپراتور نمیتواند تا مدتها بعد یک انفجار را از یک باگ، یا یک باگ را از یک نفوذ تشخیص دهد.
جایی که این فقدانها وجود دارند، یک عامل آنها را سریعتر از یک تیم انسانی پیدا و استفاده میکند، نه به این دلیل که باهوشتر است، بلکه به این دلیل که خسته نمیشود. حالت شکست بهندرت یک نفوذ چشمگیر است. خستگی و نویز است: قفلشدن حسابهایی که کاربران واقعی را از کار میاندازد، افت سرویس تحت بار بازتلاش، و وضعیت خراب از نوشتنهای جزئی مکرر. یک سیستم قدیمی که هرگز بیش از چند صد نوشتن در ساعت ندیده است ممکن است هزاران نوشتن ببیند، و فرضهایش درباره سریالسازی و حل تعارض برقرار نخواهد ماند.

یک سازوکار مشخص این را خوانا میکند. یک endpoint قدیمی SOAP یا REST را در نظر بگیرید که یک عملیات createRecord را بدون کلید idempotency و بدون سهمیه بهازای هر principal ارائه میدهد. یک حلقه عامل واحد با سیاست بازتلاش در timeout، تحت یک بکاند کند، همان نوشتن منطقی را چندین بار صادر میکند. هر تلاش برای سرور معتبر به نظر میرسد. نتیجه یک حادثه امنیتی به معنای کلاسیک نیست؛ یک حادثه کیفیت داده است که سپس باید بهصورت دستی آشتی داده شود. در یک ازدحام ضرب کنید و هزینه آشتیدادن آسیب واقعی است.
کنترلهایی که در مرز کار میکنند
جای مفید برای مداخله، مرز عامل است — لایه بین چارچوب عامل و رابط قدیمی — نه داخل خود چارچوب عامل. کنترلهای داخل چارچوب توصیهای هستند؛ عامل میتواند بازتنظیم شود و یک چارچوب متفاوت آنها را به اشتراک نمیگذارد. کنترلهای مرزی بدون توجه به اینکه کدام عامل، فروشنده یا اسکریپت فراخوانی میکند اعمال میشوند.
سه کنترل بیشترین وزن را حمل میکنند.
بودجه درخواست بهازای هر principal روی رابطهای قدیمی، اعمالشده بیرون از چارچوب عامل. یک gateway در مقابل سیستم قدیمی درخواستها را بهازای هر principal، هر endpoint، هر پنجره میشمارد و فراتر از بودجه را رد یا صفبندی میکند. بودجه باید از تحمل اثباتشده سیستم قدیمی تنظیم شود، نه از جاهطلبی عامل. این یک تصمیم ظرفیت است به همان اندازه که یک تصمیم امنیتی است.
الزامات idempotency برای هر مسیر نوشتنی که یک عامل ممکن است به آن برسد. هر فراخوانی نوشتن یک کلید تولیدشده توسط کلاینت حمل میکند. gateway یا سرویس کلید را با نتیجه ذخیره میکند و تکرار همان کلید نتیجه اصلی را برمیگرداند بهجای انجام دوباره نوشتن. این تغییری کوچک در قرارداد رابط و تغییری بزرگ در حالت شکست است: بازتلاشها ایمن میشوند و خرابی نوشتن جزئی از انباشتهشدن بازمیایستد.
آینهسازی فقطخواندنی برای کاوش. بگذارید عاملها برای هر چیز کاوشی به یک replica پرسوجو کنند. سیستم مرجع را پشت فراخوانیهای صریح و حسابرسیشده نگه دارید. کاوش جایی است که عاملها بیشترین ترافیک و کمترین ارزش بهازای هر فراخوانی را تولید میکنند؛ همچنین جایی است که یک replica کهنه کمترین آسیب را دارد. این معاوضه صادقانه است: یک replica تأخیر تکرار را معرفی میکند و عاملی که از replica میخواند و سپس به سیستم مرجع مینویسد ممکن است بر وضعیت کهنه عمل کند. این برای جستوجو و تریاژ قابل تحمل است و برای جریانهای کاری تراکنشی قابل تحمل نیست. مرز باید این تمایز را صریح کند بهجای واگذار
agent -> boundary gateway -> legacy interface
|
|- principal identity
|- per-endpoint budget
|- idempotency store
|- audit log (append-only)
|- read/write routing (replica vs system of record)

gateway جایی است که یک درخواست منتسب، شمرده، رفعتکرار و ثبت میشود. همچنین جایی است که یک تغییر سیاست در چند دقیقه اعمال میشود نه در یک چرخه انتشار.
چرا بازنویسی اولین حرکت اشتباه است
برنامههای جایگزینی سالها طول میکشند. آنها همچنین تمایل دارند با همان استدلال توجیه شوند — که املاک قدیمی ناایمن است — که یعنی پرونده ایمنی برای تأمین مالی پروژهای استفاده میشود که مواجهه این فصل را کاهش نخواهد داد. در همین حال ریسک تقویت اثر زنده است. یک ازدحام عامل منتظر تکمیل مهاجرت نمیماند.
کنترلهای مرزی سه ویژگی دارند که جایگزینی ندارد. آنها نسبت به بازنویسی ارزان هستند، چون در مقابل املاک مینشینند نه داخل آن. آنها قابل آزمون هستند، چون یک بودجه و یک انبار idempotency میتوانند با بار مصنوعی پیش از اعتماد آزمایش شوند. و آنها برگشتپذیر هستند، چون یک سیاست gateway میتواند در صورت اثبات بیشازحد سختگیرانه بودن شل شود. بازنویسی هیچیک از اینها نیست.
یک مزیت مرتبه دوم وجود دارد که آسان از دست میرود. همان کنترلها آسیب ناشی از اتوماسیون معمولی بدتنظیم را کاهش میدهند. یک cron job با باگ بازتلاش، یک اسکریپت که روی یک خطای گذرا حلقه میزند، یک یکپارچهسازی بدتنظیم که یک صف را بازپخش میکند — اینها علل روزمره حوادث قدیمی هستند. بودجههای بهازای هر principal و کلیدهای idempotency همزمان با تقویت اثر عامل به آنها میپردازند. این ویژگی نادری در کار زیرساخت است: یک کنترل، دو دسته آسیب.
اول چه باید کرد
توالی عملی کوتاه است. رابطهای قدیمی که یک عامل میتواند به آنها برسد را فهرست کنید و برای هر یک ثبت کنید که آیا بودجه بهازای هر principal، کلید idempotency روی نوشتنها و ردپای حسابرسی قابل انتساب دارد. یک gateway در مقابل آنهایی که ندارند قرار دهید. بودجهها را از تحمل مشاهدهشده تنظیم کنید. خواندنهای کاوشی را به یک replica مسیردهی کنید. سپس، و تنها سپس، تصمیم بگیرید که آیا خود املاک نیاز به جایگزینی دارد — و اگر دارد، کنترلهای مرزی همچنان همان چیزی خواهند بود که املاک را در حین ساخت جایگزین ایمن نگه میدارد.
ادعا اینکه عاملها سیستمهای قدیمی را تازه خطرناک میکنند نیمهدرست است. آنها آنها را تازه آسیبپذیر نمیکنند. آنها آسیبپذیری موجود را ارزانتر برای بهرهکشی میکنند، و این یک مسئله توان عملیاتی است با یک پاسخ توان عملیاتی.
