یادداشتها راهنما
جاوا، اسپرینگ، کوبرنتیز
نقشهای از اینکه واقعاً چطور نرمافزار بکاند را اجرا میکنم: جاوا روی JVM، اسپرینگ بهعنوان لایهی برنامه، و کوبرنتیز بهعنوان جایی که برنامه در آن زندگی میکند. از اینجا شروع کنید، بعد سراغ یادداشتی بروید که با مسئلهی پیش روی شما میخواند.
این یک فهرست آموزشی نیست. این ترتیبی است که یک همتیمی را بعد از یک حادثه از آن عبور میدهم.
اگر تازه اینجا آمدهاید
@Transactionalاسپرینگ آن چیزی نیست که فکر میکنید — اینکه تراکنشها واقعاً کجا شروع میشوند، و چرا متدی که رویthisمتد دیگری را صدا میزند بیسروصدا هیچ کاری نمیکند.- زندهبودن با سالمبودن فرق دارد — آن اختلال کوبرنتیز که شبیه حلقهی کرش به نظر میرسد ولی از یک وابستگی کُند شروع شده است.
- درسهای قابلیت اطمینان از SQLite — چرا ابزاری که مسئلههای بیشتری حل میکند تا بسازد، در محیط عملیاتی ماندگار میشود.
دورهی جاوا مسیر بلندتر است، برای وقتی که بخواهید این پشته را با من بنویسید، نه فقط دربارهاش بخوانید.
جاوا / JVM
دارید یک stack trace را در محیط عملیاتی میخوانید. یاد بگیرید از پایین بخوانیدش: اول کد خودتان، بعد فریمورک، بعد کانتینر. خط اول بهندرت علت است.
دارید سر نخها بحث میکنید. اسپرینگ MVC بهصورت پیشفرض یعنی یک درخواست، یک نخ. ExecutorService برای کاری است که بتوانید نامش را ببرید و محدودش کنید. async بیحدومرز همان راهی است که یک جهش تأخیر را به قطعی استخر نخ تبدیل میکند.
دارید JVM را قبل از اندازهگیری تنظیم میکنید. اندازهی هیپ، لاگهای GC و نرخ تخصیص حافظه از یک -Xmx آیینی بهترند. تا وقتی نموداری از زمان مکث تحت بار واقعی نداشته باشم، الگوریتم GC را عوض نمیکنم.
اسپرینگ
یک متد را در @Transactional پیچیدهاید و پایگاهداده هنوز نظر دیگری دارد. یادداشت تراکنش را بخوانید. فراخوانی درونکلاسی، REQUIRED در برابر REQUIRES_NEW، و قواعد rollback سه باگی هستند که هنوز در بازبینی کد میبینم.
قواعد کسبوکار را در کنترلر گذاشتهاید. کنترلرها HTTP را تجزیه میکنند. سرویسها مالک مرز تراکنشاند. اگر متد سرویس را نشود بدون MockMvc از یک تست صدا زد، مرز اشتباه است.
چهار پروفایل دارید و هیچکدام با محیط عملیاتی نمیخواند. local، test و prod کافیاند. پرچمهای قابلیت جایشان در پیکربندی است، نه در پنجمین فایل YAML که هیچکس مستقرش نمیکند.
کوبرنتیز
پادها ریاستارت میشوند و تیم برنامه کلاستر را مقصر میداند. یادداشت پروبها را بخوانید. اگر liveness به پایگاهداده بزند، کوبرنتیز فرایندهای سالم را میکُشد، فقط چون یک وابستگی کُند بوده است.
محدودیت CPU گذاشتهاید چون «کارمان همین است». محدودیتها throttle میکنند. آنچه زمانبند باور دارد، requestهاست. من requestها را از مصرف اندازهگیریشده تعیین میکنم و در گذاشتن محدودیت CPU روی JVMهای حساس به تأخیر دستبهعصا هستم.
نمیتوانید بگویید یک پاد آمادهی گرفتن ترافیک هست یا نه. readiness دقیقاً برای همین است. پروبهای startup وجود دارند تا بوت کُند یک JVM در دقیقهی اول بهدست liveness کشته نشود.
آنچه باور داشتم ← آنچه حالا میکنم
قبلاً اسپرینگ و کوبرنتیز را دو مهارت جدا میدیدم: یکی برای نوشتن سرویسها، یکی برای «عملیات». حالا آنها را یک زماناجرای واحد میبینم. مرز تراکنشی که در اسپرینگ اشتباه باشد، به توفان تلاش مجدد تبدیل میشود و کوبرنتیز با خوشحالی تقویتش میکند.
نکتههای کلیدی
- از خرابی پیش روی خودتان شروع کنید، نه از صفحهی شروعبهکار فریمورک.
@Transactionalیک پروکسی است. اگر ندانید پروکسی کجا نشسته، تراکنشی در کار نیست.- liveness نباید به همان چیزهایی وابسته باشد که پاد برای انجام کارش لازم دارد.
- جاوا، اسپرینگ و کوبرنتیز بهصورت یک سامانه خراب میشوند. بهصورت یک سامانه اشکالزداییشان کنید.