You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: 08- Working Asynchronously/README.md
+17-18
Original file line number
Diff line number
Diff line change
@@ -62,9 +62,9 @@
62
62
63
63
یک فرآیند تقریباً به شرح زیر است:
64
64
65
-
1.مشتری یک سرویس را از طریق کانالی مانند REST، RPC یا UDP فراخوانی می کند. همچنین اندپوینتی را برای اطلاع از آماده شدن نتیجه فراهم می کند.
65
+
1.کلاینت یک سرویس را از طریق کانالی مانند REST، RPC یا UDP فراخوانی می کند. همچنین اندپوینتی را برای اطلاع از آماده شدن نتیجه فراهم می کند.
66
66
67
-
2. فراخوانی بلافاصله بر میگردد
67
+
2. فراخوانی(callback) بلافاصله بر میگردد
68
68
69
69
3. زمانی که کار تکمیل شد، سرویس اندپوینت تعریف شده را فراخوانی می کند تا به فرستنده اطلاع دهد.
70
70
@@ -83,7 +83,7 @@
83
83
3. واسط (broker) پیام را به همه مشترکین (subscribers) ارسال می کند
84
84
85
85
86
-
یک broker این امکان را دارد که فرستنده و گیرنده(sender and receiver) را به جهات مختلف جدا می کند. علاوه بر این، کارگزار می تواند بسیاری از وظایف اضافی مانند کامل تبدیل فیلتر کردن پیام، را انجام دهد. این الگو کاملاً مقیاس پذیر است و از این رو در میان افزارهای(middleware) سازمانی محبوب است.
86
+
یک broker این امکان را دارد که فرستنده و گیرنده(sender and receiver) را به جهات مختلف جدا می کند. علاوه بر این، broker می تواند بسیاری از وظایف اضافی مانند کامل تبدیل فیلتر کردن پیام، را انجام دهد. این الگو کاملاً مقیاس پذیر است و از این رو در میان افزارهای(middleware) سازمانی محبوب است.
87
87
88
88
ابزار Celery از مکانیسمهای انتشار/اشتراک (pub/sub) برای انتقال دیتای درونی خود استفاده میکند، مانند Redis در ارسال پیام.
89
89
@@ -109,14 +109,14 @@
109
109
- ماژول asyncio: ماژول داخلی پایتون برای اجرای همزمان چندین کار در یک نخ
110
110
- فریمورک django channel: معماری مشابه صف پیام در زمان واقعی برای مدیریت رویدادهای I/O مانند WebSockets
111
111
112
-
بیایید ابتدا محبوب ترین و قوی ترین راه حل برای اجرای وظایف به صورت ناهمزمان(asynchronous) را درک کنیم: Celey
112
+
بیایید ابتدا محبوب ترین و قوی ترین راه حل برای اجرای وظایف به صورت ناهمزمان(asynchronous) را درک کنیم: Celery
113
113
114
114
115
115
## کار کردن با Celery
116
116
117
-
ابزار Celery یک مدیر صف وظایف ناهمزمان با ویژگی های غنی است. در اینجا، یک وظیفه به یک فراخوانی اشاره دارد که هنگام اجرا، فعالیت را به صورت ناهمزمان انجام می دهد. Celey توسط چندین سازمان معروف از جمله اینستاگرام و موزیلا برای انجام میلیون ها کار در روز در تولید استفاده می شود.
117
+
ابزار Celery یک مدیر صف تسک های ناهمزمان با ویژگی های غنی است. در اینجا، یک تسک به یک فراخوانی اشاره دارد که هنگام اجرا، فعالیت را به صورت ناهمزمان انجام می دهد. Celery توسط چندین سازمان معروف از جمله اینستاگرام و موزیلا برای انجام میلیون ها تسک که در طول روز تولید میشوند استفاده می شود.
118
118
119
-
هنگام نصب Celery، باید اجزای مختلفی مانند broker و جایی برای ذخیره دیتا را انتخاب کنید. اگر گیج شده اید، توصیه می کنم Redis را نصب کنید و برای شروع از مکان دخیره دیتا صرفنظر کنید. از آنجایی که Redis به صورت in-memorty کار می کند، اگر پیام های شما بزرگتر هستند و نیاز به ماندگاری دارند، باید به جای آن از RabbitMQ استفاده کنید. برای شروع میتوانید مراحل اول با celery و استفاده از celery با جنگو را در راهنمای کاربر celery دنبال کنید.
119
+
هنگام نصب Celery، باید اجزای مختلفی مانند broker و جایی برای ذخیره دیتا را انتخاب کنید. اگر گیج شده اید، توصیه می کنم Redis را نصب کنید و برای شروع از مکان ذخیره دیتا صرف نظر کنید. از آنجایی که Redis به صورت in-memorty کار می کند، اگر پیام های شما بزرگتر هستند و نیاز به ماندگاری دارند، باید به جای آن از RabbitMQ استفاده کنید. برای شروع میتوانید مراحل اول با celery و استفاده از celery با جنگو را در راهنمای کاربر celery دنبال کنید.
120
120
121
121
122
122
در جنگو، تسک های Celery معمولاً در یک فایل جداگانه به نام tasks.py در کنار فایل های یک app میآید.
@@ -135,7 +135,7 @@ def fetch_feed(feed_id):
135
135
```
136
136
این تسک محتوای یک فید RSS را بازیابی کرده و در پایگاه داده ذخیره می کند.
137
137
138
-
به نظر می رسد یک تابع عادی پایتون است (حتی اگر مربوط به یک کلاس باشد)، جز دکوریتور @shared_task. این یک تسک celery را مشخص می کند. یک تسک مشترک(shared task) می تواند توسط اپ های دیگر در همان پروژه استفاده شود. این کار را با ایجاد نمونه های مستقل از کار در هر برنامه ثبت شده، قابل استفاده مجدد می کند.
138
+
به نظر می رسد یک تابع عادی پایتون است (حتی اگر مربوط به یک کلاس باشد)، جز دکوریتور @shared_task. این یک تسک celery را مشخص می کند. یک تسک مشترک(shared task) می تواند توسط اپ های دیگر در همان پروژه استفاده شود. این کار با ایجاد نمونه های مستقل از کار در هر برنامه ثبت شده، قابل استفاده مجدد می کند.
139
139
140
140
برای فراخوانی این تسک می توانید از متد delay() به صورت زیر استفاده کنید:
زمانی که یک درخواست می رسد، می توان یک Celery task را برای رسیدگی به آن آن فعال کرد.Celery بلافاصله بدون مسدود کردن بقیه درخواست ها یک مقداری برمیگردد. در واقع، اجرای کار به پایان نرسیده است، اما یک پیام task وارد یک صف task (یا یکی از بسیاری از صف های موجود) شده است.
156
+
زمانی که یک درخواست می رسد، می توان یک Celery task را برای رسیدگی به آن آن فعال کرد.Celery بلافاصله بدون مسدود کردن بقیه درخواست ها یک مقداری برمیگردد. در واقع، اجرای کار به پایان نرسیده است، اما یک پیام task وارد یک صف task (یا یکی از از صف های متعدد موجود) شده است.
157
157
158
158
کارگران سلری(workers) فرآیندهای جداگانه ای هستند که بر صف ها نظارت می کنند که اگر یک task جدید رسید آن ها را اجرا کنند. آن ها انجام یک کار (task) را برعهده میگیرند و یک پیام برگشت (acknowledgment) به صف میفرستند تا این task از صف ما حذف شود. سپس آن task را اجرا کنند پس از انجام این task این فرآیند تکرار می شود و worker یک task جدید را برای اجرا انتخاب می کند.
159
159
@@ -171,9 +171,9 @@ def fetch_feed(feed_id):
171
171
172
172
### Handling failure
173
173
174
-
هر نوع خطا می تواند هنگام اجرای یک task در Celery اتفاق بیفتند. اگر مکانیزمی برای مدیریت این خطاها نباشد واین خطاها ممکن است شناسایی نشود اغلب، یک کاری که انجام نشود موقتی است، مانند یک API (که خارج از کنترل ما است) یا تمام شدن حافظه. در چنین مواردی، بهتر است صبر کنید و دوباره کار را امتحان کنید.
174
+
هر نوع خطا می تواند هنگام اجرای یک task در Celery اتفاق بیفتند. باید مکانیزمی برای مدیریت این خطاها و تلاش مجدد باشد اگر این مکانیزم نباشد این خطاها شناسایی نمی شوند، اگر خطایی در کار رخ دهد موقتی است، مانند یک API (که خارج از کنترل ما است) یا تمام شدن حافظه. در چنین مواردی، بهتر است صبر کرد و دوباره کار را با فاصله های زمانی امتحان کرد.
175
175
176
-
در Celery، میتوانید انتخاب کنید که به صورت خودکار یا دستی در صورت خطا دوباره امتحان کند.
176
+
در Celery، میتوانید انتخاب کنید که به صورت خودکار یا دستی در صورت خطا آن تسک را دوباره امتحان کند.
177
177
Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد خودکار خود را آسان می کند. در مثال زیر، چندین پارامتر برای تلاش مجدد را مشخص می کنیم:
این تکنیک انتظار طولانیتر و طولانیتر برای تلاش مجدد، exponential backoff نامیده میشود. این برای تعامل با یک سرور خارجی ایده آل است زیرا ما به سرور خارجی زمان کافی برای بازیابی می دهیم.
193
193
194
-
یک نوسان تصادفی برای جلوگیری از مشکلی موسوم به thundering herds اضافه شده است. اگر تعداد زیادی از کارها الگوی تکرار مجدد یکسانی داشته باشند و در همان زمان منبعی را درخواست کنند، ممکن است آن را غیرقابل استفاده کند.
194
+
یک نوسان تصادفی(آرگومان jitter) برای جلوگیری از مشکلی موسوم به thundering herds اضافه شده است. اگر تعداد زیادی از کارها الگوی تکرار مجدد یکسانی داشته باشند و در همان زمان منبعی را درخواست کنند، ممکن است آن را غیرقابل استفاده کند.
195
195
196
196
از این رو، یک عدد تصادفی به دوره انتظار اضافه می شود تا چنین اتفاقاتی رخ ندهد.
همانطور که دیدیم، کارهای Celery ممکن است چندین بار مجدداً راه اندازی شوند، به خصوص اگر acknowledgment با تاخیر را فعال کرده باشید. این امر کنترل side effect را یک کار را مهم می کند. از این رو، celery توصیه می کند که همه کارها باید خودتوان باشد. خودتوان یک امر ریاضی است
217
+
همانطور که دیدیم، کارهای Celery ممکن است چندین بار مجدداً راه اندازی شوند، به خصوص اگر acknowledgment با تاخیر را فعال کرده باشید. این امر کنترل side effect را یک کار مهم می کند. از این رو، celery توصیه می کند که همه کارها باید خودتوان باشد. خودتوان یک امر ریاضی است
218
218
ویژگی یک تابع که است که اطمینان می دهد اگر با همان آرگومان ها فراخوانی شود، بدون توجه به اینکه چند بار آن را فراخوانی کنید، همان نتیجه را برمی گرداند.
219
219
220
220
ممکن است نمونههای سادهای از عملکردهای بیتوان را در خود مستندات Celery دیده باشید، مانند این:
مهم نیست که چند بار این تابع را فراخوانی کنیم، نتیجه add(2,2) همیشه 4 است.
228
228
229
-
با این حال، درک تفاوت بین یک عملکرد بیتوان و عملکردی که عوارض جانبیندارد (عملکرد خالص یا پوچ) مهم است. عارضه جانبی یک idempotent یکسان خواهد بود، صرف نظر از اینکه یک بار یا چند بار خوانده شده باشد
229
+
با این حال، درک تفاوت بین یک تابع خودتوان و تابعی که عوارض جانبی(side effect) ندارد (تابع خالص یا پوچ) مهم است. توابع خودتوان همواره یک عارضه جانبی(side effect) ثابت دارند ، صرف نظر از اینکه یک بار یا چند بار صدا زده شده اند
230
230
231
-
با این حال درک تفاوت یک یک فانکشن خود توان و یک فانکشن معمولی که side effects ندارد مهم است. موضوع side effects یک فانکشن خودتوان یصرف نظر از اینکه چندبار صدا زده شود یکسان خواهد بود.
231
+
با این حال درک تفاوت یک یک فانکشن خود توان و یک فانکشن معمولی که side effects ندارد مهم است. موضوع side effects یک فانکشن خودتوان صرف نظر از اینکه چندبار صدا زده شود یکسان خواهد بود.
232
232
233
233
برای مثال، تسکی که همیشه هنگام فراخوانی یک آبجکت از نوع order ایجاد می کند، یک فانکشن خودتوان نیست، اما تسکی که یک سفارش موجود را لغو می کند، خودتوان است. عملیات هایی که فقط حالت اشیا را می خوانند و هیچ اثر جانبی(side effect) ندارند، یک فانکشن خودتوان نیستند.
234
234
235
235
از آنجایی که معماری celery متکی بر تسک های خودتوان است، مهم است که سعی کنید تمام عوارض جانبی یک تسکی که خودتوان نیست را مطالعه کنید و آن را به یک کار غیر خودتوان تبدیل کنید. میتوانید این کار را با بررسی اینکه آیا تسک ها قبلاً اجرا شدهاند (اگر اجرا شدهاند، پس تسک حذف شده است) یا با بررسی اینکه آیا نتیجه تسک در یک آدرس یونیک بر اساس آرگومانها ذخیره شده است یا نه انجام دهید. در قسمت های بعدی کتاب (بخش Avoid writing to shared or global state) یک مثال ازین مورد آورده شده است.
236
236
237
237
در نتیجه، تسک خود را چندین بار صدا کنید تا بررسی کنید که آیا سیستم شما در همان حالت باقی می ماند یا خیر.
238
238
239
-
### از نوشتن در دیتابیس در فانکشن هایی به صورت shared یا global خودداری کنید
239
+
### از عملیات نوشتن بر روی دیتابیس در فانکشن هایی به صورت shared یا global خودداری کنید
240
240
241
241
در یک سیستم همزمان، می توانید چندین خواننده داشته باشید. با این حال، لحظهای که نویسندگان زیادی به یک وضعیت مشترک دسترسی پیدا میکنند، ممکن است دچار بن بست (deadlocks) یا شرایط رقابتی(race condition) آسیبپذیر میشوید. برای پرهیز از همه اینها کمی برنامه ریزی و نبوغ لازم است.
### به روز رسانی پایگاه داده بدون شرایط رقابتی(race condition)
267
267
268
-
ممکن است با موقعیتهایی مواجه شوید که بهروزرسانی وضعیت مشترک اجتنابناپذیر باشد. اگر دیتابیس شما از قابلیت row-level locks پشتیبانی کند میتوانید ازین مورد یا از اشیا Django F() استفاده کنید قایل ذکر است دیتابیس mysql چون از موتور MyISAM استفاده می کند این قابلیت را پشتیبانی نمی کند.
268
+
ممکن است با موقعیتهایی مواجه شوید که مجبور باشید یک آبجکت را در یک تابع مشترک (shared function) در دیتابیس بهروزرسانی کنید. اگر دیتابیس شما از قابلیت row-level locks پشتیبانی کند میتوانید ازین مورد یا از اشیا Django F() استفاده کنید قایل ذکر است دیتابیس mysql چون از موتور MyISAM استفاده می کند این قابلیت را پشتیبانی نمی کند.
269
269
270
270
از قابلیت row-level locks در جنگو با استفاده از متد select_for_update() در کوئری ست میتوانید استفاده کنید. مثال زیر را ببینید:
271
271
@@ -277,8 +277,7 @@ with transaction.atomic():
277
277
feed.save()
278
278
```
279
279
280
-
با استفاده از select_for_update() ما سطر های آبجکت Feed اصطلاحا قفل (lock) میکند که تا زمانی که ترنزکشن ما تمام نشد اجازه ایجاد و تغییر در دیتابیس نداشته باشیم.
281
-
280
+
با استفاده از select_for_update() سطر های آبجکت Feed اصطلاحا قفل (lock) میشود که تا زمانی که ترنزکشن ما تمام نشد اجازه ایجاد و تغییر در دیتابیس نداشته باشیم.
282
281
اگر نخ یا فرآیند دیگری قبلاً همان ردیف را قفل کرده باشد، کوئری منتظر می ماند یا کوِئری تا زمانی که lock در دیتابیس تمام شود مسدود می شود. این رفتار را می توان با استفاده از پارامترهای کلمه کلیدی select_for_update تغییر داد تا یک خطا ایجاد کند یا در صورت قفل از آن رد شود.
283
282
284
283
اگر عملیات روی یک فیلد را بتوان در دیتابیس انجام داد بهتر است از فانکشن F() برای جلوگیری از شرایط رقابتی(race condition) استفاده شود. فانکشن F() از گرفتن دیتا از دیتابیس و انتقال به مموری پایتون برای انجامیک عملیات جلوگیری می کند و این کار را مستقیم بر روی دیتابیس انجام می دهد. به مثال زیر توجه کنید:
0 commit comments