راهنمای عمیق معماری پلاگین با بهار ، کنسول و شتر

_0 ++++++++++++++++++++++++++++++++++++++++++ img src = “https://hackernoon.com/avatars/4CIXILaY2ySzhSciNTLA9bzYzBo2.png” alt = “عکس نمایه نویسنده”>

jadamJames Adam

توسعه دهنده نرم افزار

طی چند ماه گذشته من روی یک ابزار مدیریت داده کار کرده ام که OpenDMP را فراخوانی می کنم. با شروع افزودن ویژگی های بیشتر ، کمی زودتر از آنچه که انتظار داشتم با مشکل مقیاس پذیری روبرو شدم و بنابراین تصمیم گرفتم به مقابله با آنچه بزرگترین قطعه باقیمانده در ساختار سیستم پروژه است بپردازم.

نیاز به پلاگین ها

از نمودار معماری بالای این پست ، احتمالاً می توانید بگویید که “پردازشگر خدمات” جایی است که بیشتر کارها برای OpenDMP انجام می شود.

گردش اطلاعات توسط کاربران در یک برنامه وب طراحی شده و سپس به سرویس پردازنده تحویل داده می شود که مسیرهای Apache Camel را برای بلعیدن ، تبدیل و سپس ذخیره نتایج تنظیم می کند. من می خواستم به کاربران اجازه دهم اسکریپت ها ، برنامه ها و / یا ابزارهای دلخواه را بر روی داده های خود اجرا کنند زیرا جریان آنها را رد می کند ، بنابراین من انواع مختلف پردازنده هایی را ایجاد کردم که کاربران می توانند به جریان خود اضافه کنند تا این کار را انجام دهد.

ابتدا پردازنده اسکریپت ، که به کاربران اجازه می دهد اسکریپت های Python یا Clojure خود را برای تبدیل داده های خود وارد کرده و سپس در سرویس پردازنده اجرا شوند.

پردازنده اسکریپت با استفاده از پایتون

دوم ، پردازنده خارجی ، که یک دستور دلخواه را در پوسته سیستم عامل اجرا می کند.

خارجی پردازنده

مشکل است؟ همه سرویس های OpenDMP در کانتینرها اجرا می شوند ، به این معنی که هرگونه ابزار خارجی که می خواهید در جریان داده خود اجرا کنید باید در Container Contenter قرار داشته باشد (از نظر تئوری کاربر می تواند تصویر پردازنده opendmp را گسترش دهد و هرگونه وابستگی مورد نیاز خود را به آن اضافه کند) )

این بدیهی است که مقیاس بندی نخواهد شد ، زیرا در صورت نیاز به افزودن بیش از چند وابستگی ، در نهایت با یک تصویر سرویس پردازنده بسیار متورم مواجه خواهید شد. به عنوان مثال پردازنده اسکریپت ، قبلاً از من خواسته بود که پشتیبانی پایتون (همراه با چند کتابخانه اصلی مانند numpy) را به تصویر پایه اضافه کنم ، که به طور قابل توجهی اندازه تصویر را افزایش می دهد.

متوجه شدم وقتی شروع به آزمایش سایر ابزارها مانند imagemagick و ffmpeg با پردازنده خارجی کردم ، این راه حل جواب نمی داد. بنابراین لازم بود که چیز متفاوتی ارائه دهم. من از اوایل ایده پلاگین ها را داشتم ، بنابراین تصمیم گرفتم به جای ادامه دادن به تعویق انداختن آن ، اکنون با این مسئله مقابله کنم. من فهمیدم که می توانم برای انجام کاری که می خواستم با پردازنده اسکریپت انجام دهم ، از پلاگین ها نیز استفاده کنم – همه موارد پایتون را از تصویر پایه خارج کنید 🙂

پردازنده پلاگین

بنابراین ، نوع پردازنده جدیدی وارد کنید: پردازشگر پلاگین.

پردازنده پلاگین یکی از پردازنده های مرکز است

ایده این است که پلاگین ها در ظروف مخصوص خود اجرا می شوند و قرار است این کار را انجام دهند یک چیز خاص در مثال بالا ، داده ها به محفظه ای با FFMPEG نصب شده ارسال می شوند ، که خط فرمان ffmpeg را که توسط کاربر مشخص شده است بر روی داده ها اجرا می کند و نتیجه را به جریان باز می گرداند.

ایده ساده ، اما این موضوع پیچیدگی جدیدی را در سیستم وارد می کند. من دیگر مجموعه مستقیمی از خدمات در حال اجرا ندارم. یعنی OpenDMP هیچ راهی برای دانستن اینکه چه افزونه هایی در هر نصب دلخواه اجرا می شوند (بدون ذکر امکان چندین مورد از پلاگین ها) راهی ندارد.

بنابراین ، اولین چیزی که می دانستم به آن احتیاج دارم راه حل Service Discovery بود. برای این کار ، کنسول هاشیکورپ را انتخاب کردم. هم توسط Apache Camel و هم از طریق Spring Boot پشتیبانی می شود ، بنابراین من فهمیدم که این امر ادغام را آسان تر می کند.

خود کنسول برای اجرای کار ساده بود. تصاویر موجود در هاب docker به خوبی کار می کنند و چرخاندن یک خوشه کوچک آسان بود.

< p class = "paragraph"> سلام نگاه کن! این افزونه من است!

Apache Camel پشتیبانی از تماس با سرویس های خارجی را به عنوان بخشی از مسیر Camel از طریق ServiceCall EIP فراهم می کند. همراه با Spring Boot Cloud ، Camel به طور خودکار از یک کنسول برای یک نمونه موجود س theال می کند و با سرویس درخواستی تماس می گیرد و نتیجه را دوباره به مسیر شتر می رساند.

البته ، در اینجا رسیدگی به خطا اهمیت پیدا می کند – ما به خدمات خارجی که ممکن است اجرا شوند یا نباشند و ورودی کاربر و / یا داده هایی که ممکن است منجر شوند یا نباشند اعتماد می کنیم. گفت: سرویس پرتاب خطا.

خوشبختانه ، Camel امکان تعیین یک کنترل کننده خطا را به صورت سراسری ، براساس هر مسیر یا هر پردازنده فراهم می کند ، بنابراین من برای اطمینان از اینکه از خطای کنترل کننده DeadLetter استفاده کردم استفاده کردم می تواند خطاها را به سرویس گردش اطلاعات گزارش دهد تا بتواند مورد توجه کاربر قرار گیرد.

از آنجا که احساس می کنم باید یک مثال کد را در جایی از این پست قرار دهم ، نحوه کار من این است متر تماس با خدمات خارجی در سرویس پردازنده. توجه داشته باشید که من از Camel’s Circuit Breaker EIP نیز استفاده می کنم ، زیرا قبلاً با چنین مشکلی روبرو شدم که خطایی منجر به بی نهایت تلاش شتر برای ارسال همان درخواست بد به یک پلاگین شد 🙂

/ ** * تماس تلفنی برقرار کنید! * / خصوصی سرگرم کننده سرویس تماس (مسیر: RouteDefinition ، پرو : ProcessorRunModel) { val service = proc.properties ؟.get ( “serviceName” ) .toString () val params = getQueryParams (proc) مسیر .log ( “برقراری تماس با $ service ) .circuitBreaker (). inheritErrorHandler ( درست ) .serviceCall () .serviceCallConfiguration ( “basicServiceCall” ) .name (سرویس) .uri ( “http: // $ service / process؟ $ {getQueryParams (proc)} ) .پایان() .endCircuitBreaker () .log ( “” تماس با $ service تکمیل شد “) .removeHeaders ( “CamelServiceCall *” ) }

پیکربندی قابل برنامه ریزی

علاوه بر تعیین اینکه چه افزونه ای اجرا شود ، احتمالاً لازم است کاربران برای برخی افزونه ها برخی پارامترها را مشخص کنند. به عنوان مثال ، در مورد پلاگین ساده FFMPEG ، سوئیچ ها و گزینه های خط فرمان برای ارائه به FFMPEG. بنابراین ، چگونه باید جلوی OpenDMP بداند که یک پلاگین تصادفی به چه پارامترهایی نیاز دارد؟

برای حل این مسئله ، تصمیم گرفتم که یک افزونه برای نشان دادن دو نقطه پایان مورد نیاز باشد: ” / روند “، برای پردازش داده ها به عنوان بخشی از جریان و” / پیکربندی “، برای ارائه اطلاعات پیکربندی به OpenDMP.

در اینجا یک مثال پاسخ پیکربندی از پلاگین ffmpeg وجود دارد:

{ “opendmp-ffmpeg-plugin” : { “serviceName” : “opendmp-ffmpeg-plugin” ، “displayName” : “پردازنده FFMPEG” ، “type” : “EXTERNAL” ، “زمینه ها” : { “دستور” : { “type” : “STRING” ، “لازم” است : درست است ، “helperText” : “خط فرمان عبور به FFMPEG” } ، “مهلت” : { “type” : “NUMBER” ، “لازم” است : نادرست ، “helperText” : “مدت زمان (در چند ثانیه) صبر برای تکمیل FFMPEG” } } }
}

به سرویس گردش اطلاعات لیستی از نام های افزونه فعال شده به عنوان یک متغیر محیط داده می شود. سپس از تمام افزونه های فعال شده (البته بازیابی اطلاعات نمونه از کنسول) برای اطلاعات پیکربندی آنها پرس و جو می کند. سپس UI می تواند این اطلاعات پیکربندی را برای یک پلاگین خاص بازیابی کرده و از آن برای ساختن فرم برای کاربر استفاده کند.

قابلیت توسعه پذیری

بنابراین ، با استفاده از پلاگین ها ، می توان تقریباً هر توانایی را که می خواهیم به OpenDMP اضافه کنیم. از آنجا که سرویس های پلاگین از طریق HTTP ارتباط برقرار می کنند ، یک پلاگین می تواند به هر زبانی پیاده سازی شود. در حال حاضر ، من کمی SDK را در Kotlin برای استفاده از JVM جمع می کنم ، اما ایجاد یک SDK ساده برای مثلاً پایتون بعداً باید یک کار ساده باشد. من همچنین قصد دارم از قابلیت پلاگین برای پردازنده های دیگر (به ویژه اسکریپت ها) “زیر کاپوت” استفاده کنم تا برخی از وابستگی ها را از ظرف اصلی پردازنده سرویس خارج کنم و البته بار CPU آن سرویس را کاهش دهم.

بنابراین ، این یک طیف وسیعی از امکانات را برای شما باز می کند – یک پلاگین Tensorflow که در یک ظرف آگاه از CUDA اجرا می شود یکی از نمونه های احتمالی است.

با تشکر از مطالعه ، اگر شما علاقه مند به جستجوی برخی از کد ها هستید ، مخزن کد OpenDMP را در اینجا بررسی کنید.

قبلاً در https://jamesadam.me/2020/10/04/a-plugin-architecture-with-spring-consul-and-camel/