<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد قلع گر</title>
        <link>https://virgool.io/feed/@m.ghalgar</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 16:29:33</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1972338/avatar/5ccgt3.jpg?height=120&amp;width=120</url>
            <title>محمد قلع گر</title>
            <link>https://virgool.io/@m.ghalgar</link>
        </image>

                    <item>
                <title>داستان  Covariance و Contravariance در C# به زبان آدمیزاد !</title>
                <link>https://virgool.io/@m.ghalgar/%D8%AF%D8%A7%D8%B3%D8%AA%D8%A7%D9%86-covariance-%D9%88-contravariance-%D8%AF%D8%B1-c-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%A2%D8%AF%D9%85%DB%8C%D8%B2%D8%A7%D8%AF-mrdqu6tz9zed</link>
                <description>می دونیم که در C# :اگرclass Drived : Base {}آنگاه  Base base=new Drived(); ولی در جنریک نمی تونیم تایپ ها رو به جای هم استفاده کنیم مگر اینکه از Covariance یا Contravariance استفاده کنیمCovariance : &lt;out T&gt;اگر می خوای بتونی یک متغیر از جنس اینترفیس/دلیگیت جنریک رو به متغیر دیگری از همون اینترفیس/دلیگیت با تایپ بالاتر تبدیل کنی در تعریف جنریک از عبارت out استفاده کننکته : در اون اینترفیس/دلیگیت نمی تونی هیچ ورودی از جنس اون تایپ داشته باشیدر واقع خروجی با تایپ پایین تر به تایپ بالاتر Cast خواهد شداگر :public interface IEnumerable&lt;out T&gt; : System.Collections.IEnumerableآنگاه :IEnumerable&lt;Derived&gt; d = new List&lt;Derived&gt;(); IEnumerable&lt;Base&gt; b = d;Contravariance : &lt;in T&gt;اگر می خوای بتونی یک متغیر از جنس اینترفیس/دلیگیت جنریک رو به متغیر دیگری از همون اینترفیس/دلیگیت با تایپ پایین تر تبدیل کنی در تعریف جنریک از عبارت in استفاده کننکته : در اون اینترفیس/دلیگیت نمی تونی هیچ خروجی از جنس اون تایپ داشته باشیدر واقع ورودی با تایپ پایین تر به تایپ بالاتر Cast خواهد شداگر :public delegate void Action&lt;in T&gt;(T obj);آنگاه :Action&lt;Base&gt; b = (target) =&gt; { Console.WriteLine(target.GetType().Name); };Action&lt;Derived&gt; d = b;</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Sun, 19 Feb 2023 00:27:59 +0330</pubDate>
            </item>
                    <item>
                <title>پروژه صف نانوایی ! + سورس کد</title>
                <link>https://virgool.io/@m.ghalgar/%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%B5%D9%81-%D9%86%D8%A7%D9%86%D9%88%D8%A7%DB%8C%DB%8C-%D8%B3%D9%88%D8%B1%D8%B3-%DA%A9%D8%AF-skdpnil3ys7s</link>
                <description>لینک سورس کد در گیت هاب اگه تا حالا نونوایی رفته باشید حتما می دونید که معمولا باید توی صف بمونید تا نوبتتون بشه و عموما براساس تعداد نان درخواستی صف ها متفاوت هستند .منطق صف های متفاوت در نانوایی اینه که کسی که درخواست نان کمتری داره زمان کمتری توی صف بمونه اما به دلیل پیچیدگی اجرا و محدودیت تعداد صف ها معمولا به درستی این منطق اجرا نمیشه .من قصد دارم توی این پروژه یک صف منصفانه رو برای یک نانوایی طراحی کنم .امکاناتی که باید این برنامه داشته باشد :هر کسی وارد نانوایی می شود تعداد نان را اعلام نماید و نوبت بگیردتعداد نان محدودیتی نداشته باشدابتدا باید ببینیم با چه الگوریتمی می تونیم یه صف منصفانه برای درخواست های وزن دار (تعداد مختلف نان درخواستی) داشته باشیم .به نظر میاد بهترین و ساده ترین راه اینه که فقط یک صف داشته باشیم و در این صف به هر فرد یک نان فروخته  شود و اگر فرد قصد خرید چند نان داشت باید چند بار در صف بماند .این روش از نظر منصفانه بودن راهکار خوبی است اما مشکلی که دارد پیچیدگی برای کاربر و بیات شدن نان است . اگر  نرم افزار بتواند این رفتار را شبیه سازی کند با این تفاوت که یکبار به هر فرد اعلام نوبت نماید هر دو مشکل رفع خواهد شد .نرم افزار بایستی دو اکشن را پشتیبانی نماید :ورود فرد جدید به صفاعلام آماده شدن هر نانپیاده سازی :برای پیاده سازی بایستی یک صف داشته باشیم که عملکرد صفی که در راهکار ما بود را شبیه سازی نماید .هر فردی که وارد نانوایی بشود به انتهای این صف اضافه می شود و به ازای هر نانی که پخته شود یک نفر از ابتدای صف حذف خواهد شد و یک نان در سبد کاربر ذخیره خواهد شد و در صورتی که نان های ذخیره شده کمتر از تعداد درخواستی باشد مجددا به انتهای صف اضافه می شود .برای نگهداری تعداد کل درخواستی هر فرد ، تعداد موجود در سبد و شماره نوبت ،  یک لیست جداگانه نیاز داریم .هر نانی که پخته می شود تعداد نان های آماده یکی اضافه خواهد شد و بررسی می شود اگر کاربر اولویت اول (فردی که  نان های در سبد و تعداد درخواستی ش اختلاف کمتری داشته باشد و زودتر وارد صف شده باشد) با نان های آماده موجود سفارشش تامین می شود خرید تکمیل شده و از صف و لیست حذف خواهد شد .لینک سورس کد در گیت هاب </description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Sat, 04 Feb 2023 15:53:47 +0330</pubDate>
            </item>
                    <item>
                <title>مختصری در مورد برنامه نویسی parallel و asynchronous و روش انجام در .net</title>
                <link>https://virgool.io/@m.ghalgar/%D9%85%D8%AE%D8%AA%D8%B5%D8%B1%DB%8C-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-parallel-%D9%88-asynchronous-%D9%88-%D8%B1%D9%88%D8%B4-%D8%A7%D9%86%D8%AC%D8%A7%D9%85-%D8%AF%D8%B1-net-koixyabzmvtd</link>
                <description>برنامه نویسی parallel و asynchronous چیست ؟برنامه نویسی parallel  = multi threaded: استفاده همزمان از چند Thread  - هر یک از Thread ها می توانند sync یا async پردازش را انجام دهند .برنامه نویسی asynchronous : عملیات زمانبر ، Thread رو معطل نگه نمی دارد و تا زمان اتمام عملیات ، Thread قابلیت پاسخگویی به سایر درخواست ها را دارد .فایده برنامه نویسی parallel و asynchronous چیست ؟برنامه نویسی parallel : سرعت انجام عملیات بیشتر خواهد شد چون همزمان از چند هسته cpu استفاده می کنیمبرنامه نویسی asynchronous : تعداد درخواست همزمان بیشتری را می توان پردازش کرد .کاربرد برنامه نویسی parallel و asynchronous چیست ؟برنامه نویسی parallel : وقتی چند کار همزمان داریم که الزاما نباید پشت سر هم انجام شوند .برنامه نویسی asynchronous : وقتی پردازش io-bound داریم مثل کار با فایل / دیتابیس / فراخوانی apiبرنامه نویسی parallel و asynchronous در .net چگونه است ؟برنامه نویسی parallel : استفاده از ParallelFor , ParallelForeach , WhenAll , WaitAll / ساخت Thread جدید در برنامه / await نکردن Task ها  .برنامه نویسی asynchronous : استفاده از Task ها و متدهای Async</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Thu, 02 Feb 2023 11:53:07 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی چالش های Caching</title>
                <link>https://virgool.io/@m.ghalgar/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-%DA%86%D8%A7%D9%84%D8%B4-%D9%87%D8%A7%DB%8C-caching-corr7snvidnc</link>
                <description>معمولا برای افزایش سرعت کوئری ها(هر جایی که قراره دیتایی به کاربر نشون بدیم) ، کش استفاده می شود ولی مشکل از جایی شروع خواهد شد که دیتای اصلی آپدیت شود ولی کش آپدیت نشود .افزایش سرعت الزاما همیشه با استفاده از کش در رم (مثل Redis) نخواهد بود و ممکن است افزایش سرعت با استفاده از رویکرد CQRS و جداسازی Read Model ها باشد که همچنان دغدغه های بروزرسانی Read Model مطرح خواهد بود رویکردهای آپدیت Cache :۱- تعیین زمان انقضایک رویکرد مرسوم و ساده در پیاده سازی کش ، تعیین زمان انقضا برای کش می باشد . در این روش خروجی کوئری ها در کش قرار می گیرد و یک زمان قطعی / شناور برای کش تعیین خواه‌د شد که تا پایان آن زمان دیتا مستقیم از کش خوانده می شود و بعد از آن دیتای کش حذف خواهد شد و کوئری های بعدی از دیتابیس گرفته شده و وارد کش می شود . احتمالا در یک سری نرم افزارها رد پای این رویکرد رو دیدید به اینصورت که وقتی دیتایی رو تغییر می دید با تاخیر در خروجی تاثیرش رو می بینید .مزایا :سادگی در پیاده سازی Command ها : هنگام بروزرسانی دیتا ، نگرانی بابت اینکه چه کش هایی روی این دیتا هست نداریم سادگی در پیاده سازی کش : در این روش به سادگی می تونیم براساس فیلترهای ورودی یک کلید بسازیم و کل دیتای خروجی رو به عنوان value در قالب کش key-value ذخیره کنیممعایب :تاخیر در بروزرسانی دیتای کشالزام در آپدیت کش بعد از زمان مشخص حتی در صورت عدم آپدیت دیتابیسمناسب برای : دیتایی که توسط کاربر تغییر نمی کند : مثلا یک سایت اطلاع رسانی رو در نظر بگیرید که اطلاعات صرفا از پنل مدیریت تغییر می کنددیتایی که توسط کاربران تغییر می کند ولی نیازی نیست در لحظه آپدیت شوند : مثلا امتیاز  یک غذا در اپلیکیشن سفارش غذا - این امتیاز براساس میانگین امتیازات کاربران به این غذا تعیین می شود اما نیازی نیست بلافاصله پس از ثبت هر نظر این عدد رو آپدیت کنیم ۲- آپدیت / حذف کش هنگام بروزرسانی دیتادر این روش با هر تغییری که در دیتای اصلی اتفاق بیفتد کش هم بروزرسانی می شودانواع بروزرسانی : بروزرسانی همزمان کش و دیتابیس اشکال اول این روش زمانی هست که تغییر در دیتابیس انجام شود ولی کش با موفقیت تغییر نکند اشکال دوم کاهش سرعت بروزرسانی دیتا هستش چون ممکن است ساختن دوباره دیتای کش نیاز به دیتای زیادی داشته باشد و یا تعداد کش های وابسته به این دیتا زیاد باشد  حذف کش هنگام بروزرسانی دیتابیس - اولین کوئری از دیتابیس خوانده خواهد شد و در کش نیز قرار خواهد گرفتدر‌این روش می توانیم قبل از بروزرسانی دیتابیس ، کش رو حذف کنیم و در صورت وجود خطا در حذف کش ، عملیات متوقف خواهد شد . منتها در فاصله زمانی بین حذف کش تا آپدیت دیتابیس بایستی از رویکردهای lock برای نوشتن دیتا در کش استفاده کنیم  مشکل دوم حل شده است اما مشکل جدید اینه که اولین کوئری زمان زیادی برای پردازش خواهد داشتحذف کش هنگام بروزرسانی دیتابیس و ثبت مجدد دیتای کش در عملیات جداگانهدر این روش معمولا بروزرسانی دیتای کش در ترد جداگانه و یا با استفاده از Message Broker ها انجام خواهد شد و مشکل کاهش سرعت اولین کوئری نیز حل خواهد شد .</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Thu, 26 Jan 2023 09:41:03 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی راهکارهای ذخیره سازی تغییرات دیتا</title>
                <link>https://virgool.io/@m.ghalgar/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-%D8%B1%D8%A7%D9%87%DA%A9%D8%A7%D8%B1%D9%87%D8%A7%DB%8C-%D8%B0%D8%AE%DB%8C%D8%B1%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1%D8%A7%D8%AA-%D8%AF%DB%8C%D8%AA%D8%A7-sqvk1adx5l5f</link>
                <description>معمولا آخرین نسخه دیتا در بانک اطلاعاتی ذخیره می شود و اگر به تغییرات دیتا از ابتدا تاکنون نیاز داشته باشیم بایستی با یک راهکاری تغییرات را ذخیره کنیمچرا به تغییرات دیتا نیاز داریم ؟- نیازمندی Debug : برخی مواقع ممکن است وضعیت فعلی دیتا براساس یک باگ در نرم افزار به وجود آمده باشد و برای رفع باگ نیاز داریم وضعیت قبلی دیتا رو داشته باشیم تا شبیه سازی درستی انجام بدیم- امکان Undo : برخی مواقع به دلیل انصرات کاربر از یک عملیات یا صلاحدید های دیگر نیاز به بازگشت به وضعیت قبلی داریم که بایستی دیتای قبلی در دسترس باشد .- نمایش History : برای امور پشتیبانی و یا در برخی از بیزنس ها نیاز به مشاهده ی تغییرات دیتا از ابتدا تاکنون برای نیروی پشتیبان یا خود کاربر می باشد .راهکارهای ذخیره سازی تغییرات :- روش Action Log : در این روش ، آدرس و دیتای متدهایی که توسط کاربر فراخوانی شده است ذخیره می شود - روش DataBase Log : در این روش ، از هر ردیف جداول دیتابیس قبل از تغییر ، یک کپی در جدول لاگ ایجاد می کنیم .- روش Domain Event : در این روش ، تغییراتی که در Aggregate ها اتفاق می افتاد در یک جدول ذخیره می شود .  Action Log :روش پیاده سازی :با استفاده از یک Action Filter یا Middleware اطلاعات Request شامل Url , Headers , Body و همچنین اطلاعات Response شامل Status Code , Headers , Body را ذخیره سازی می کنیم .براساس نیازمندی می توانیم اطلاعات Command ها یا Query ها یا هر دو را براساس HttpMethod تفکیک و ذخیره سازی کنیم .ضمنا امکان لاگ کردن همه ی درخواست ها و یا صرفا خطاها براساس Status Code خواهد بود .محل ذخیره سازی پیشنهادی برای این روش Elastic می باشد که با استفاده از ابزار Kibana امکان نمایش و جستجوی لاگ ها را فراهم می کند .مزایا :- امکان ذخیره سازی لاگ Query ها- امکان ذخیره سازی لاگ خطاهای درخواست / سرور که منجر به تغییر دیتا نشده اند- امکان جستجوی لاگ براساس متدها- سادگی پیاده سازیمعایب :- عدم امکان ایجاد ارتباط دقیق بین لاگ ها و دیتاهای جداول مختلف- حجم زیاد لاگ ها به دلیل نگهداری کلیه ی دیتای ارسالی / دریافتی متدها- عدم امکان UndoDataBase Log :روش پیاده سازی :به ازای هر جدول ، یک Trigger روی Insert , Update , Delete می گذاریم و کل فیلدهای جدول را در جدول دیگری همراه با id ردیف تغییر کرده ذخیره می کنیم دیتای لاگ ممکن است به صورت serilize شده در یک فیلد قرار گیرد (امکان نگهداری لاگ همه ی جداول در یک جد.ول) و یا به ازای هر فیلد در جدول اصلی ، یک فیلد در جدول لاگ داشته باشیم (نیاز به جدول لاگ مجزا به ازای هر جدول) .امکان پیاده سازی در داخل نرم افزار نیز وجود دارد به عنوان مثال در Ef Core می توانیم متد SaveChange را بازنویسی کرده و با استفاده از Change Tracker تغییرات را دریافت و در جدول جداگانه ای ذخیره نموده و با یک Transaction روی دیتابیس اعمال نماییم .در صورت نیاز به Undo فقط کافیست ردیف لاگ مورد نظر به جای دیتای اصلی در دیتابیس قرار گیرد.مزایا :- ارتباط دقیق بین ردیف های دیتابیس و لاگ تغییرات- امکان انجام خودکار با استفاده از Trigger ها- سادگی پیاده سازی- امکان Undoمعایب :- حجم زیاد لاگ ها به دلیل نگهداری کلیه ی دیتا در هر تغییر- پیچیدگی تشخیص دقیق تغییرات در هر عملیاتDomain Event :روش پیاده سازی :این روش مناسب معماری های مبتنی بر رویکرد DDD می باشد . در هر متد Aggregate Root یک Domain Event مجزا منتشر می شود که شامل دیتای دریافتی در آن متد می باشد و Domain Event ها همراه با ذخیره سازی سایر دیتا ها در جدول جداگانه ای شامل AggregateId , AggregateType , EventType , EventData , Time , UserId ذخیره می شوند .برای افزایش خوانایی ایونت ها می توانیم متد ToString داخل هر نوع ایونت را بازنویسی کرده و براساس نوع ایونت و دیتای ورودی یک متن خوانا تولید نماییم و هنگام نمایش ایونت ها به جای دیتای خام ، این متن را نمایش دهیم .در صورت نیاز به امکان Undo و بازگشت به نسخه خاصی از دیتا ، بایستی Aggregate Root براساس ساختار Event Sourcing پیاده سازی شده باشد و لیست ایونت ها از ابتدا تا زمانی که دیتا بایستی به آن نسخه تغییر کند از دیتابیس دریافت و به ترتیب روی Aggregate Root اعمال می گردد .معایب :- پیچیدگی پیاده سازی (مناسب معماری های خاص)- عدم امکان ذخیره سازی لاگ Query هامزایا :- ارتباط دقیق بین لاگ تغییرات و Aggregate ها- تشخیص دقیق تغییرات در هر عملیات- امکان Undo (نیاز به ساختار Event Sourcing) رویکرد پیشنهادی :اگر از معماری های مبتنی بر DDD استفاده می کنید روش Domain Event را برای ذخیره سازی تغییرات دیتا استفاده کنید و خطاهای 500 را با استفاده از روش Action Log  جهت دیباگ مشکلات نرم افزار ذخیره کنید . ذخیره سازی لاگ کوئری ها به دلیل حجم زیاد ، توصیه نمی شود و اگر نیازمندی آماری دارید استفاده از prometheus توصیه می شود .در صورت نیاز می توانید خطاهای 400 را برای رفتارسنجی کاربران ذخیره نمایید .</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Thu, 19 Jan 2023 15:07:32 +0330</pubDate>
            </item>
                    <item>
                <title>رویکرد پیشنهادی برای ارسال / دریافت ایونت در معماری Event Driven</title>
                <link>https://virgool.io/@m.ghalgar/%D8%B1%D9%88%DB%8C%DA%A9%D8%B1%D8%AF-%D9%BE%DB%8C%D8%B4%D9%86%D9%87%D8%A7%D8%AF%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A7%D8%B1%D8%B3%D8%A7%D9%84-%D8%AF%D8%B1%DB%8C%D8%A7%D9%81%D8%AA-%D8%A7%DB%8C%D9%88%D9%86%D8%AA-%D8%AF%D8%B1-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-event-driven-bixyw8p2rkab</link>
                <description>در معماری Event Driven بخش مهمی از ارتباط بین سرویس ها از طریق Message و در بستر Message Broker می باشد .این Message ها ممکن است Event یا Command باشند .ایونت ها از وقوع اتفاقی در گذشته خبر می دهند و کامندها برای اجرای دستور خاصی می باشند .معمولا ایونت ها به صورت Broadcast ارسال می شوند (یک فرستنده و نامحدود گیرنده) و کامندها به صورت Direct (یک فرستنده و یک گیرنده مشخص) ارسال می شوند .این مطلب در مورد ایونت هاست  و راهکاری برای کاهش برخی از مشکلات این نوع پیام ارائه می دهد .مثال :برای ارسال ایونت ، یک مثال ساده می تواند این باشد که در یک ساختار میکروسرویس ، یکی از سرویس ها سرویس User می باشد و سایر سرویس ها بخشی از اطلاعات کاربران را با هدف کاهش وابستگی نزد خود نگه می دارند مثلا سرویس Comment اسم ، تصویر و آی دی کاربر را در دیتابیس خود نگه می دارد که هنگام نمایش لیست کامنت ها اسم کاربر را نیز نمایش دهد بدون اینکه نیاز به ارسال درخواست به سرویس User باشد .در این مثال هر زمانی که کاربر جدیدی ثبت می شود یا نام کاربری تغییر می کند سرویس User یک ایونت برای سایر سرویس ها ارسال می کند که اطلاعات یوزر را بروزرسانی کنند .برخی از مشکلاتی که ممکن است در این روش وجود داشته باشد :عدم تطابق ترتیب دریافت ایونت ها با ترتیب ارسال آنها : با وجود اینکه ساختار Message Broker ها براساس صف (و طبیعتا رعایت ترتیب) می باشد اما بعضی مسائل مانند خواندن همزمان چند پیام از روی صف ممکن است ترتیب پردازش ایونت ها رو تغییر دهد .جاافتادن یک ایونت در سرویس گیرنده : در رویکرد Event Driven هیچ زمانی به صورت 100% نمی توان مطمئن بود که پیام های ارسالی توسط سرویس های دیگر دریافت و پردازش شود . حال اگر یک پیام پردازش نشود و پیام های بعدی مربوط به آن Object (مثلا یک کاربر خاص در مثال ما) پردازش شود ممکن است برای همیشه دیتای مربوطه ناقص بماندتنوع زیاد  ایونت های ارسالی : اگر ایونت های ارسالی مربوط به یک object پیچیده با تعداد Property های زیاد باشد احتمالا تنوع ایونت های ارسالی بسیار زیاد خواهد بود به عنوان مثال اگر برای تغییرات یک Product بخواهیم ایونت ارسال کنیم برخی از نوع ایونت ها شامل تغییر نام و مشخصات / تغییر قیمت / تغییر تصاویر و.. خواهند بود .نیاز به راهکار موازی برای اطمینان : اگر هنگام نیاز به اون موجودیت در سرویس گیرنده ایونت ، با یک آی دی خاص موجودیت بافت نشود مجبوریم یه api call به سرویس فرستنده ایونت بزنیم و از وجود/عدم وجود اون آی دی مطمئن شویم .راهکار پیشنهادی :برای حل این مشکل می توان به ازای هر Type یک ایونت  شامل id و UpdateTime داشت و سرویس های دریافت کننده ، صرفا یک Consumer دارند که به محض دریافت این ایونت ، اطلاعات فعلی را از سرویس اصلی دریافت کرده و پردازش مورد نیاز را انجام می دهند .در مثال بالا ، سرویس User در زمان ایجاد کاربر جدید ، بروزرسانی اطلاعات کاربر و حذف کاربر ایونتی را ارسال خواهد کرد با نام UserChanged و شامل آی دی کاربر و زمان وقوع اتفاق .هر سرویس دیگری (مانند سرویس کامنت) هنگام دریافت این ایونت ، Api سرویس User را صدا زده و کلیه اطلاعات کاربر را دریافت خواهد کرد و دیتای خود را بروزرسانی می کند .چالش این راهکار ، نیاز به Api Call در زمان پردازش ایونت هاست که به دلایل زیر مشکلی ایجاد نمی کند :کاهش Performance : معمولا سرویس های میکروسرویس آمادگی پاسخدهی به تعداد زیادی Query دارند بنابرین اضافه شدن یک Api Call به ازای هر ایونت / سرویس ، هزینه خاصی را به سرویس فرستند تحمیل نمی کند .وابستگی سرویس ها : اگر در زمان پردازش ایونت ، سرویس فرستنده به هر دلیلی امکان ارائه دیتا نداشت با استفاده از رویکردهای retry در Consumer ها پردازش پیام به زمان دیگری موکول خواهد شد .</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Thu, 05 Jan 2023 11:19:28 +0330</pubDate>
            </item>
                    <item>
                <title>Eventual Consistency در میکروسرویس</title>
                <link>https://virgool.io/@m.ghalgar/eventual-consistency-%D8%AF%D8%B1-%D9%85%DB%8C%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-trar1fohtmqf</link>
                <description>Eventual ConsistencyEventual Consistency چیه ؟Eventual Consistency یعنی دیتا در دو یا چند سرویس به صورت قطعی یکسان نیست و احتمالا یکسان است و ممکن است با تاخیر سینک شوند .چرا Eventual Consistency به وجود میاد ؟در میکروسرویس ها با هدف مستقل بودن هر سرویس ، از ارتباط های همزمان بین دو سرویس دوری می شود و سعی در ارتباط از طریق Message (Events,Commands) می باشد و از آنجایی که ضمانتی روی دریافت پیام ها وجود ندارد ممکن است دیتا در سایر سرویس ها با تاخیر بروزرسانی شود .به عنوان مثال یک فروشگاه اینترنتی را در نظر بگیرید که سرویس انبارداری از سرویس سفارشات جداست ، بعد از اینکه یک سفارش ثبت می شود سرویس سفارشات یک پیام برای سرویس انبارداری می کند که موجودی محصول را کاهش دهد ، حالا اگر این پیام به سرعت پردازش نشود ممکن است کاربر دیگری این محصول را سفارش دهد در صورتی که موجودی به پایان رسیده باشد .با Eventual Consistency چه کنیم ؟بپذیرید !معمولا افرادی که تجربه کار با معماری  Monolithic را دارند هنگام شروع کار با معماری Microservice یکی از چالش های جدی شون همین مبحث Eventual Consistency هست . درسته که با راه هایی می تونیم این مشکل رو بهبود بدیم ولی باید بپذیریم که این مساله در ذات این معماری هست و اگر نمی تونیم باهاش کنار بیایم بهتره سراغ معماری میکروسرویس نریم !در تفکیک سرویس ها به این موضوع فکر کنیدیکی از اولین گام های طراحی معماری میکروسرویس ، تفکیک سرویس های مختلف می باشد ، برای اینکه از عواقب Eventual Consistency در امان باشید در هنگام تفکیک سرویس ها باید این نکته رو در نظر بگیرید که هر سرویس دارای دیتابیس جداگانه می باشد و دیتایی که از سایر سرویس ها دارد ممکن است با تاخیر به روز شود بنابراین دیتاهایی که وابستگی شدید به هم دارد رو در یک سرویس قرار بدید .در طراحی محصول به این موضوع فکر کنیدیکی از راه های کاهش مشکلات ناشی از Eventual Consistency تطبیق طراحی محصول براساس تفکیک سرویس ها می باشد . به عنوان مثال در بخش نمایش لیست محصولات اگر این امکان را داشته باشید که دکمه افزودن به سبد خرید را غیرهمزمان با دریافت اطلاعات محصول نشان دهید ، بعد از دریافت لیست محصولات از سرویس انبارداری ، موجودی هر محصول را استعلام می کنید و در صورت موجود بودن ، دکمه اضافه به سبد خرید را نمایش می دهید .از راهکارهای اطمینان بخش استفاده کنیدبرای افزایش سرعت بروزرسانی اطلاعات در سرویس های مختلف می توانیم علاوه بر پیام هایی که از طریق Message Broker ها ارسال می شوند تسک های زمان بندی شده برای بروزرسانی اطلاعات داشته باشیم به عنوان مثال اگر اطلاعات در یک سرویس 1 با ایونت های سرویس 2 بروز می شود سرویس 1 می تواند هر چند ساعت سرویس 2 را فراخوانی کند و تغییرات را دریافت نماید .شما از چه راهکاری برای این مساله استفاده می کنید ؟</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Thu, 29 Dec 2022 13:18:05 +0330</pubDate>
            </item>
                    <item>
                <title>الگوی Outbox</title>
                <link>https://virgool.io/@m.ghalgar/%D8%A7%D9%84%DA%AF%D9%88%DB%8C-outbox-wc3mfeexu4th</link>
                <description>در این پست به این سوالات پاسخ میدم :1- الگوی Outbox چه مشکلی رو حل می کنه ؟2- الگوی Outbox چطور پیاده سازی میشه ؟3- چالش های این الگو چیه؟4- یک مثال کاربردی از Outbox1- الگوی Outbox چه مشکلی رو حل می کنه ؟در معماری میکروسرویس یا هر معماری ای که ارتباط بین سرویس ها براساس پیام هایی روی Message Broker ها (مانند RabbitMq یا Kafka) باشد ، معمولا سرویس فرستنده پیام ، همزمان با ارسال پیام بایستی دیتاهایی در دیتابیس خود نیز ثبت کند که این فرآیند به چند صورت قابل انجام است :ذخیره اطلاعات در دیتابیس سپس ارسال پیام به Message Brokerمشکل این روش این است که ممکن است اطلاعات با موفقیت ذخیره شود ولی ارسال پیام با موفقیت انجام نشود (مثلا اتصال به Message Broker انجام نشود یا ..) . بنابراین سرویس گیرنده پیام از انجام تراکنش بی خبر است و بخشی از عملیات مورد نظر انجام نخواهد شد .ارسال پیام به Message Broker سپس ذخیره اطلاعاتمشکل این روش برعکس روش قبلی است یعنی ممکن است پیام ارسال شود ولی اطلاعات با موفقیت ذخیره نشود (مثلا اتصال به دیتابیس انجام نشود یا ..) . بنابراین سرویس گیرنده پیام ، پیام اشتباه دریافت خواهد کرد و ممکن است در فرآیند کاری سیستم اختلال ایجاد شود ، مشکل دیگر این روش این است که حتی اگر هر دو عملیات موفقیت آمیز انجام شود ممکن است ذخیره سازی اطلاعات در دیتابیس کمی طول بکشد و در این فاصله ، سرویس گیرنده پیام را دریافت و پردازش کند و ترتیب اجرای عملیات با مشکل مواجه شود .استفاده از Two-phase commitمشکل این روش این است که توسط برخی از دیتابیس ها پشتیبانی نمی شود .استفاده از الگوی Outboxاین روش موضوع این مقاله است و مشکلات روش های قبلی را ندارد و اصطلاحا atomically عملیات ذخیره اطلاعات و ارسال پیام را انجام می دهد .2- الگوی Outbox چطور پیاده سازی میشه ؟یک جدول در دیتابیس با نام outbox اضافه می شود و هنگام ذخیره اطلاعات ، پیام هایی که باید به Message Broker ارسال شوند همزمان با سایر اطلاعات در این جدول ذخیره می شوند .یک سرویس خودکار ، هر چند ثانیه یکبار لیست پیام های جدول Outbox را خوانده و به Message Broker ارسال می نماید و از جدول حذف می کند .با این روش ، مطمئن هستیم که پیام بعد از ذخیره سازی موفق دیتا ، ارسال خواهد شد و ضمنا مطمئن هستیم که پیام ارسال خواهد شد .اگر ذخیره سازی اطلاعات با مشکل مواجه شود پیام ها نیز در جدول outbox ذخیره نخواهند شد (به دلیل اینکه کل اطلاعات با یک تراکنش به دیتابیس ارسال شده است) .اگر ارسال پیام ها به Message Broker با مشکل مواجه شود ، مجددا چند ثانیه دیگر برای ارسال تلاش خواهد شد و این چرحه تا زمان ارسال موفق پیام ها ادامه پیدا خواهد کرد .نکته 1 : می توانید به جای حذف پیام ها از جدول Outbox ، یا یک فیلد bit وضعیت ارسال را تغییر دهید ، این راهکار به شما کمک می کند تا سابقه ارسال پیام ها را در دیتابیس داشته باشید .نکته 2 : برای رعایت ترتیب ارسال پیام ها ، بایستی هنگام ارسال پیام ها را به ترتیب ثبت در جدول واکشی و ارسال کنیم و ضمنا از ارسال موازی پیام ها خودداری کنیم .3- چالش های این الگو چیه؟تنها مشکل این الگو این است که ممکن است پس از ارسال موفق پیام ، عملیات حذف پیام از جدول outbox با موفقیت انجام نشود .راهکار این مشکل Idempotent بودن سرویس گیرنده پیام می باشد . یعنی اگر چند بار یک پیام یکسان را دریافت کرد فقط یکبار پردازش انجام دهد .4- یک مثال کاربردی از Outboxفرض کنید در یک سایت فروشگاهی بعد از ثبت سفارش بایستی پیامک به خریدار ارسال گردد و سرویس سفارش و پیامک جدا هستند .کاربر سرویس سفارش را فراخوانی می کند و درخواست ثبت سفارش را ارسال می نمایند سفارش ساخته شده و همزمان با ثبت اطلاعات سفارش ، دستور ارسال پیام به کاربر نیز در قالب یک Message در جدول Outbox ثبت می گردد و پیام &quot;سفارش با موفقیت ثبت شد&quot; به کاربر نمایش داده می شود .یک سرویس خودکار پیام را از جدول خوانده و به Message Broker ارسال می نماید .سرویس پیامک ، Message را از Broker دریافت نموده و به خریدار پیام ارسال می کند .</description>
                <category>محمد قلع گر</category>
                <author>محمد قلع گر</author>
                <pubDate>Wed, 21 Dec 2022 20:50:07 +0330</pubDate>
            </item>
            </channel>
</rss>