JavaRush /وبلاگ جاوا /Random-FA /راهنمای میکروسرویس های جاوا. بخش 1: مبانی و معماری میکروس...

راهنمای میکروسرویس های جاوا. بخش 1: مبانی و معماری میکروسرویس ها

در گروه منتشر شد
در این راهنما، می آموزید که میکروسرویس های جاوا چیست، چگونه آنها را طراحی و ایجاد کنید. همچنین سوالاتی در مورد کتابخانه های میکروسرویس جاوا و امکان استفاده از میکروسرویس ها را پوشش می دهد. ترجمه و اقتباس از Microservices جاوا: راهنمای عملی .

جاوا میکروسرویس: اصول

برای درک میکروسرویس ها، ابتدا باید تعریف کنید که چه چیزی نیستند. آیا یک "مونولیت" نیست - یکپارچه جاوا: چیست و مزایا یا معایب آن چیست؟ راهنمای میکروسرویس های جاوا.  بخش 1: مبانی و معماری میکروسرویس ها - 1

یکپارچه جاوا چیست؟

تصور کنید برای یک بانک یا یک استارت آپ فین تک کار می کنید. شما یک اپلیکیشن موبایلی را در اختیار کاربران قرار می دهید که می توانند از آن برای باز کردن یک حساب بانکی جدید استفاده کنند. در کد جاوا این منجر به حضور یک کلاس کنترلر می شود. ساده شده، به نظر می رسد این است:
@Controller
class BankController {

    @PostMapping("/users/register")
    public void register(RegistrationForm form) {
        validate(form);
        riskCheck(form);
        openBankAccount(form);
        // etc..
    }
}
شما به کنترلر نیاز دارید تا:
  1. فرم ثبت نام را تایید کرد.
  2. خطرات آدرس کاربر را بررسی کرد تا تصمیم بگیرد که آیا یک حساب بانکی به او ارائه دهد یا خیر.
  3. حساب بانکی باز کرد
کلاس BankControllerبه همراه بقیه منابع شما در یک فایل bank.jar یا bank.war برای استقرار بسته بندی می شود - این یک مونولیت قدیمی خوب است که حاوی تمام کدهای مورد نیاز برای اجرای بانک شما است. به عنوان یک تخمین تقریبی، اندازه اولیه یک فایل jar (یا .war) از 1 تا 100 مگابایت متغیر است. اکنون می توانید به سادگی فایل jar را روی سرور خود اجرا کنید... و این تنها کاری است که برای استقرار برنامه جاوا خود باید انجام دهید. راهنمای میکروسرویس های جاوا.  بخش 1: مبانی و معماری میکروسرویس ها - 2تصویر، مستطیل بالا سمت چپ: استقرار یک بانک تک (لیتیک) جاوا -jar bank.jar (cp .war/.ear در سرور برنامه). مستطیل راست: مرورگر را باز کنید.

مشکل یکپارچه های جاوا چیست؟

هیچ مشکلی ذاتاً با یکپارچه‌های جاوا وجود ندارد. با این حال، تجربه نشان داده است که اگر در پروژه شما:
  • برنامه نویسان / تیم ها / مشاوران زیادی در حال کار هستند ...
  • ... بر روی همان یکپارچه تحت فشار مشتریان با الزامات بسیار مبهم ...
  • در عرض یکی دو سال ...
... در این صورت فایل bank.jar کوچک شما به تنهایی به یک گیگابایت کد عظیم تبدیل می شود که حتی نزدیک شدن به آن ترسناک است، چه رسد به استقرار.

چگونه اندازه یک مونولیت جاوا را کاهش دهیم؟

یک سوال طبیعی مطرح می شود: چگونه یکپارچه را کوچکتر کنیم؟ در حال حاضر bank.jar شما روی یک JVM، یک فرآیند روی یک سرور در حال اجرا است. نه بیشتر نه کمتر. و در حال حاضر ممکن است یک فکر منطقی به ذهن خطور کند: "اما خدمات تأیید خطر می تواند توسط سایر بخش های شرکت من استفاده شود! ارتباط مستقیمی با برنامه بانکداری یکپارچه من ندارد! شاید باید از یکپارچه خارج شود و به عنوان یک محصول جداگانه به کار گرفته شود؟ یعنی از نظر فنی، اجرای آن به عنوان یک فرآیند جاوا جداگانه.

میکروسرویس جاوا چیست؟

در عمل، این عبارت به این معنی است که اکنون فراخوانی متد riskCheck()از BankController انجام نخواهد شد: این متد یا جزء bean با تمام کلاس های کمکی خود به پروژه Maven یا Gradle خود منتقل می شود. همچنین مستقل از یکپارچگی بانکی مستقر شده و تحت کنترل نسخه قرار می گیرد. با این حال، کل این فرآیند استخراج ماژول جدید RiskCheck شما را به خودی خود به یک میکروسرویس تبدیل نمی کند، زیرا تعریف میکروسرویس قابل تفسیر است. این منجر به بحث های مکرر در تیم ها و شرکت ها می شود.
  • آیا 5-7 کلاس در یک پروژه میکرو است یا چه؟
  • 100 یا 1000 کلاس ... هنوز میکرو؟
  • آیا میکروسرویس به طور کلی به تعداد کلاس ها مربوط می شود یا خیر؟
بیایید استدلال نظری را پشت سر بگذاریم و در عوض به ملاحظات عمل گرایانه پایبند باشیم و این کار را انجام دهیم:
  1. بیایید همه سرویس‌های مستقر جداگانه را بدون در نظر گرفتن اندازه یا مرزهای دامنه، میکروسرویس‌ها بنامیم.
  2. بیایید به نحوه ترتیب دادن ارتباطات بین سرویس فکر کنیم. میکروسرویس های ما به راه هایی برای برقراری ارتباط با یکدیگر نیاز دارند.
بنابراین، به طور خلاصه: قبلاً یک فرآیند JVM داشتید، یکپارچگی محکم برای اجرای بانک. اکنون شما یک فرآیند JVM یکپارچه بانکی و یک میکروسرویس RiskCheck جداگانه دارید که در فرآیند JVM خود اجرا می شود. و اکنون، برای بررسی خطرات، مونولیت شما باید با این میکروسرویس تماس بگیرد. چطور این کار را بکنیم؟

چگونه بین میکروسرویس های جاوا ارتباط برقرار کنیم؟

به طور کلی و به طور کلی، دو گزینه وجود دارد - ارتباط همزمان و ناهمزمان.

ارتباط همزمان: (HTTP)/REST

به طور معمول، ارتباط همگام‌سازی شده بین میکروسرویس‌ها از طریق HTTP و سرویس‌های مشابه REST انجام می‌شود که XML یا JSON را برمی‌گردانند. البته، ممکن است گزینه های دیگری نیز وجود داشته باشد - حداقل از Google Protocol Buffers استفاده کنید . اگر نیاز به پاسخ فوری دارید، بهتر است از ارتباط REST استفاده کنید. در مثال ما، این دقیقاً همان کاری است که باید انجام شود، زیرا تأیید ریسک قبل از افتتاح حساب مورد نیاز است. اگر بررسی ریسک وجود نداشته باشد، هیچ حسابی وجود ندارد. ابزارهای زیر را در بخش « کدام کتابخانه‌ها برای تماس‌های REST همگام جاوا بهتر هستند » مورد بحث قرار خواهیم داد.

پیام رسانی - ارتباطات ناهمزمان

ارتباط میکروسرویس ناهمزمان معمولاً با تبادل پیام با اجرای JMS و/یا استفاده از پروتکلی مانند AMQP انجام می‌شود . ما "معمولا" را در اینجا به دلیلی نوشتیم: فرض کنید تعداد ادغام های ایمیل/SMTP را نمی توان دست کم گرفت. زمانی که نیاز به پاسخ فوری ندارید از آن استفاده کنید. به عنوان مثال، کاربر روی دکمه "خرید اکنون" کلیک می کند و شما نیز به نوبه خود می خواهید یک فاکتور ایجاد کنید. این فرآیند مطمئناً نباید در چرخه درخواست خرید-پاسخ کاربر رخ دهد. در زیر توضیح خواهیم داد که کدام ابزارها برای پیام رسانی ناهمزمان جاوا بهترین هستند .

مثال: REST API فراخوانی در جاوا

بیایید فرض کنیم ارتباط میکروسرویس سنکرون را انتخاب می کنیم. در این حالت، کد جاوا ما (همانی که در بالا ارائه کردیم) در سطح پایین چیزی شبیه به این خواهد بود. (در اینجا منظور ما از سطح پایین این واقعیت است که برای ارتباطات میکروسرویس، معمولاً کتابخانه های مشتری ایجاد می شوند که شما را از تماس های HTTP واقعی انتزاع می کند).
@Controller
class BankController {

    @Autowired
    private HttpClient httpClient;

    @PostMapping("/users/register")
    public void register(RegistrationForm form) {
        validate(form);
        httpClient.send(riskRequest, responseHandler());
        setupAccount(form);
        // etc..
    }
}
بر اساس کد، مشخص می شود که اکنون باید دو سرویس جاوا (micro) بانک و RiskCheck را مستقر کنیم. در نتیجه، دو فرآیند JVM در حال اجرا خواهیم داشت. راهنمای میکروسرویس های جاوا.  بخش 1: مبانی و معماری میکروسرویس ها - 3این تمام چیزی است که برای توسعه یک پروژه میکروسرویس جاوا نیاز دارید: فقط تکه های کوچکتر (فایل های jar یا .war) را به جای یک قطعه یکپارچه بسازید و بکار ببرید. پاسخ به این سوال همچنان نامشخص است: چگونه باید یکپارچه را به میکروسرویس برش دهیم؟ این قطعات چقدر باید کوچک باشند، چگونه اندازه صحیح را تعیین کنیم؟ بیایید بررسی کنیم.

معماری میکروسرویس جاوا

در عمل، شرکت ها پروژه های میکروسرویس را به روش های مختلف توسعه می دهند. این رویکرد به این بستگی دارد که آیا می‌خواهید یک پروژه یکپارچه موجود را به یک پروژه میکروسرویس تبدیل کنید یا پروژه را از ابتدا شروع کنید.

از یکپارچه تا میکروسرویس

یکی از منطقی ترین ایده ها استخراج میکروسرویس ها از یک مونولیت موجود است. توجه داشته باشید که پیشوند «micro» در اینجا در واقع به این معنی نیست که خدمات استخراج شده واقعاً کوچک خواهند بود؛ لزوماً اینطور نیست. بیایید به پیشینه نظری نگاه کنیم.

ایده: یکپارچه را به میکروسرویس ها تقسیم کنید

رویکرد میکروسرویس را می توان برای پروژه های قدیمی به کار برد. و به همین دلیل:
  1. اغلب، نگهداری/تغییر/گسترش چنین پروژه هایی دشوار است.
  2. همه، از توسعه دهندگان گرفته تا مدیریت، خواهان ساده سازی هستند.
  3. شما مرزهای دامنه (نسبتا) واضحی دارید، به این معنی که دقیقاً می دانید نرم افزار شما باید چه کاری انجام دهد.
به مثال ما برگردیم، این بدان معناست که شما می توانید به یکپارچه بانکداری جاوا خود نگاه کنید و سعی کنید آن را در سراسر مرزهای دامنه تجزیه کنید.
  • بنابراین، منطقی است که پردازش داده‌های کاربر (مانند نام، آدرس، شماره تلفن) را در یک میکروسرویس جداگانه «مدیریت حساب» جدا کنیم.
  • یا "ماژول بررسی ریسک" که سطوح ریسک کاربر را بررسی می کند و می تواند توسط بسیاری از پروژه های دیگر یا حتی بخش های شرکت استفاده شود.
  • یا یک ماژول صورتحساب که فاکتورها را در قالب PDF یا از طریق پست ارسال می کند.

اجرای یک ایده: اجازه دهید شخص دیگری آن را انجام دهد

روشی که در بالا توضیح داده شد روی کاغذ و نمودارهای UML مانند عالی به نظر می رسد. با این حال، همه چیز به این سادگی نیست. اجرای عملی آن مستلزم آمادگی فنی جدی است: شکاف بین درک ما از آنچه استخراج کردن از یکپارچه خوب است و خود فرآیند استخراج بسیار زیاد است. بیشتر پروژه‌های سازمانی به مرحله‌ای می‌رسند که توسعه‌دهندگان می‌ترسند، مثلاً نسخه ۷ ساله Hibernate را به نسخه جدیدتر ارتقا دهند. کتابخانه ها همراه با آن به روز خواهند شد، اما خطر واقعی شکستن چیزی وجود دارد. بنابراین همان توسعه دهندگان اکنون باید از طریق کدهای قدیمی قدیمی با مرزهای تراکنش پایگاه داده نامشخص و استخراج ریزسرویس های کاملاً تعریف شده را بررسی کنند؟ اغلب اوقات، این مشکل بسیار پیچیده است و نمی توان آن را در یک تخته سفید یا در جلسات معماری "حل" کرد. راهنمای میکروسرویس های جاوا.  بخش 1: مبانی و معماری میکروسرویس ها - 4به نقل از توسعه دهنده توییتر @simonbrown: من این را بارها و بارها خواهم گفت... اگر مردم نتوانند به درستی یکپارچه بسازند، میکروسرویس ها کمکی نمی کنند. سیمون براون

پروژه از ابتدا بر اساس معماری میکروسرویس

در مورد پروژه های جدید جاوا، سه نقطه شماره گذاری شده از قسمت قبل کمی متفاوت به نظر می رسند:
  1. شما با یک لوح تمیز شروع می کنید، بنابراین هیچ "چمدانی" برای نگهداری وجود ندارد.
  2. توسعه دهندگان مایلند در آینده همه چیز را ساده نگه دارند.
  3. مشکل: شما تصویر بسیار مبهم تری از مرزهای دامنه دارید: نمی دانید نرم افزار شما واقعاً قرار است چه کاری انجام دهد (اشاره: چابک ؛))
این منجر به تلاش شرکت‌ها برای انجام پروژه‌های جدید با میکروسرویس‌های جاوا می‌شود.

معماری میکروسرویس فنی

به نظر می رسد اولین نکته برای توسعه دهندگان واضح ترین نکته باشد، اما کسانی نیز هستند که به شدت آن را منع می کنند. هادی حریری بازآفرینی "Extract Microservice" را در IntelliJ توصیه می کند. و اگرچه مثال زیر بسیار ساده شده است، اما متاسفانه پیاده سازی های مشاهده شده در پروژه های واقعی از آن دور نمی شود. قبل از میکروسرویس ها
@Service
class UserService {

    public void register(User user) {
        String email = user.getEmail();
        String username =  email.substring(0, email.indexOf("@"));
        // ...
    }
}
با زیر رشته جاوا میکروسرویس
@Service
class UserService {

    @Autowired
    private HttpClient client;

    public void register(User user) {
        String email = user.getEmail();
        //теперь вызываем substring microservice via http
        String username =  httpClient.send(substringRequest(email), responseHandler());
        // ...
    }
}
بنابراین شما اساساً یک فراخوانی متد جاوا را در یک تماس HTTP بدون هیچ دلیل واضحی برای انجام این کار قرار می دهید. با این حال، یک دلیل این است: عدم تجربه و تلاش برای تحمیل رویکرد میکروسرویس جاوا. توصیه: این کار را نکنید.

معماری میکروسرویس مبتنی بر گردش کار

رویکرد متداول بعدی تقسیم میکروسرویس های جاوا به ماژول های مبتنی بر گردش کار است. مثال واقعی: در آلمان، وقتی نزد یک پزشک (عمومی) می روید، او باید ویزیت شما را در سیستم CRM پزشکی خود ثبت کند. برای دریافت پرداخت از بیمه، او داده های مربوط به درمان شما (و درمان سایر بیماران) را از طریق XML به واسطه ارسال می کند. کارگزار به این فایل XML نگاه می کند و (ساده شده):
  1. بررسی خواهد کرد که آیا فایل XML صحیح دریافت شده است.
  2. معقول بودن روش ها را بررسی می کند: مثلاً یک کودک یک ساله که سه روش تمیز کردن دندان را در یک روز از متخصص زنان دریافت کرده است تا حدودی مشکوک به نظر می رسد.
  3. XML را با برخی داده های بوروکراتیک دیگر ترکیب می کند.
  4. فایل XML را برای شروع پرداخت ها به شرکت بیمه ارسال می کند.
  5. و نتیجه را برای پزشک ارسال می‌کند و پیام «موفقیت» یا «لطفاً به محض اینکه منطقی شد، این ضبط را دوباره ارسال کنید» را برای او ارسال می‌کند.
توجه داشته باشید. در این مثال، ارتباط بین میکروسرویس ها نقشی ندارد، اما می تواند به طور ناهمزمان توسط یک واسطه پیام (به عنوان مثال RabbitMQ) انجام شود، زیرا به هر حال پزشک بازخورد فوری دریافت نمی کند. راهنمای میکروسرویس های جاوا.  بخش 1: مبانی و معماری میکروسرویس ها - 5باز هم، این روی کاغذ عالی به نظر می رسد، اما سوالات طبیعی مطرح می شود:
  • آیا برای پردازش یک فایل XML نیاز به استقرار شش برنامه کاربردی است؟
  • آیا این میکروسرویس ها واقعاً مستقل از یکدیگر هستند؟ آیا می توان آنها را مستقل از یکدیگر مستقر کرد؟ با نسخه های مختلف و طرح های API؟
  • اگر میکروسرویس تأیید صحت کار نکند، میکروسرویس قابل قبول بودن اطلاعات چه می کند؟ آیا سیستم هنوز کار می کند؟
  • آیا این میکروسرویس ها پایگاه داده یکسانی را به اشتراک می گذارند (مطمئناً به برخی از داده های رایج در جداول DB نیاز دارند)، یا هر کدام خود را دارند؟
  • … و خیلی بیشتر.
جالب توجه است که نمودار بالا ساده تر به نظر می رسد زیرا هر سرویس اکنون هدف دقیق و کاملاً تعریف شده خود را دارد. قبلاً چیزی شبیه به این یکپارچه ترسناک به نظر می رسید: راهنمای میکروسرویس های جاوا.  قسمت 1: مبانی و معماری میکروسرویس ها - 6در حالی که می توانید در مورد سادگی این نمودارها بحث کنید، قطعاً اکنون باید این چالش های عملیاتی اضافی را حل کنید.
  • شما فقط نیازی به استقرار یک برنامه ندارید، بلکه حداقل شش برنامه را نیاز دارید.
  • حتی ممکن است نیاز به استقرار چندین پایگاه داده داشته باشید، بسته به اینکه تا چه حد می خواهید به معماری میکروسرویس ها بروید.
  • شما باید مطمئن شوید که هر سیستم آنلاین است و به درستی کار می کند.
  • باید مطمئن شوید که تماس‌های شما بین میکروسرویس‌ها واقعاً انعطاف‌پذیر هستند (به نحوه انعطاف‌پذیری میکروسرویس جاوا مراجعه کنید؟).
  • و هر چیز دیگری که این تنظیم دلالت دارد - از تنظیمات توسعه محلی گرفته تا تست یکپارچه سازی.
بنابراین توصیه این خواهد بود:
  • اگر نتفلیکس نیستید (احتمالاً نتفلیکس نیستید)...
  • مگر اینکه در جایی که محیط توسعه را باز می‌کنید مهارت‌های کاری فوق‌العاده قوی داشته باشید و یک میمون آشوب را فرا می‌خواند که پایگاه داده تولید شما را دور می‌اندازد که به راحتی در 5 ثانیه بازیابی می‌شود.
  • یا احساس می کنید که @monzo هستید و می خواهید 1500 میکروسرویس را امتحان کنید فقط به این دلیل که می توانید.
→ این کار را نکنید. و اکنون کمتر هذلولی است. تلاش برای مدل‌سازی میکروسرویس‌ها در سراسر مرزهای دامنه کاملاً منطقی به نظر می‌رسد. اما این بدان معنا نیست که باید یک گردش کار را انتخاب کنید و آن را به بخش های کوچک جداگانه تقسیم کنید (دریافت XML، اعتبارسنجی XML، XML ارسال کنید). از این رو، هر زمان که پروژه جدیدی را با میکروسرویس های جاوا شروع می کنید و مرزهای دامنه هنوز بسیار مبهم است، سعی کنید اندازه میکروسرویس های خود را در سطح پایین نگه دارید. همیشه می‌توانید بعداً ماژول‌های بیشتری اضافه کنید. و مطمئن شوید که DevOps پیشرفته در تیم/شرکت/بخش برای پشتیبانی از زیرساخت جدید خود دارید.

معماری میکروسرویس چند زبانه یا تیم گرا

رویکرد سوم، تقریبا آزادانه، برای توسعه میکروسرویس‌ها وجود دارد: به تیم‌ها یا حتی افراد اجازه می‌دهد تا داستان‌های کاربر را با استفاده از هر تعداد زبان یا ریزسرویس پیاده‌سازی کنند (بازاریابان این رویکرد را «برنامه‌نویسی چند زبانه» می‌نامند). بنابراین، سرویس اعتبار سنجی XML که در بالا توضیح داده شد، می تواند در جاوا نوشته شود، در حالی که میکروسرویس اعتبارسنجی در همان زمان می تواند در Haskell نوشته شود (برای اینکه از نظر ریاضی درست شود). برای میکروسرویس حمل و نقل بیمه، می توانید از Erlang استفاده کنید (زیرا واقعاً نیاز به مقیاس دارد ;)). آنچه ممکن است از دیدگاه یک توسعه دهنده سرگرم کننده به نظر برسد (توسعه سیستم کامل با زبان کامل شما در یک محیط ایزوله) در واقع هرگز آن چیزی نیست که سازمان می خواهد: همگن سازی و استانداردسازی. این به معنای مجموعه نسبتاً استاندارد شده‌ای از زبان‌ها، کتابخانه‌ها و ابزارها است تا توسعه‌دهندگان دیگر بتوانند به پشتیبانی از میکروسرویس Haskell شما در آینده و زمانی که به مراتع سبزتر می‌روید، ادامه دهند. راهنمای میکروسرویس های جاوا.  قسمت 1: مبانی و معماری میکروسرویس ها - 8تاریخ نشان می دهد که استانداردسازی معمولاً خیلی عمیق می شود. به عنوان مثال، توسعه دهندگان در شرکت های بزرگ Fortune 500 حتی گاهی اوقات اجازه استفاده از Spring را نداشتند زیرا "بخشی از نقشه راه فناوری شرکت نبود." با این حال، گذار کامل به رویکرد چند زبانه تقریباً یک چیز است، روی دیگر همان سکه. توصیه: اگر می خواهید از برنامه نویسی چند زبانه استفاده کنید، تنوع کمتری را در اکوسیستم زبان برنامه نویسی یکسان امتحان کنید. بنابراین، بهتر است از Kotlin و Java با هم استفاده کنید (هر دو زبان مبتنی بر JVM هستند و 100٪ با یکدیگر سازگار هستند)، به جای جاوا و مثلا Haskell. در قسمت بعدی با استقرار و تست میکروسرویس های جاوا آشنا خواهید شد.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION