Skip to content

Commit 0b161a8

Browse files
Update README.md
1 parent 9113144 commit 0b161a8

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

08- Working Asynchronously/README.md

+17-18
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@
6262

6363
یک فرآیند تقریباً به شرح زیر است:
6464

65-
1. مشتری یک سرویس را از طریق کانالی مانند REST، RPC یا UDP فراخوانی می کند. همچنین اندپوینتی را برای اطلاع از آماده شدن نتیجه فراهم می کند.
65+
1. کلاینت یک سرویس را از طریق کانالی مانند REST، RPC یا UDP فراخوانی می کند. همچنین اندپوینتی را برای اطلاع از آماده شدن نتیجه فراهم می کند.
6666

67-
2. فراخوانی بلافاصله بر میگردد
67+
2. فراخوانی(callback) بلافاصله بر میگردد
6868

6969
3. زمانی که کار تکمیل شد، سرویس اندپوینت تعریف شده را فراخوانی می کند تا به فرستنده اطلاع دهد.
7070

@@ -83,7 +83,7 @@
8383
3. واسط (broker) پیام را به همه مشترکین (subscribers) ارسال می کند
8484

8585

86-
یک broker این امکان را دارد که فرستنده و گیرنده(sender and receiver) را به جهات مختلف جدا می کند. علاوه بر این، کارگزار می تواند بسیاری از وظایف اضافی مانند کامل تبدیل فیلتر کردن پیام، را انجام دهد. این الگو کاملاً مقیاس پذیر است و از این رو در میان افزارهای(middleware) سازمانی محبوب است.
86+
یک broker این امکان را دارد که فرستنده و گیرنده(sender and receiver) را به جهات مختلف جدا می کند. علاوه بر این، broker می تواند بسیاری از وظایف اضافی مانند کامل تبدیل فیلتر کردن پیام، را انجام دهد. این الگو کاملاً مقیاس پذیر است و از این رو در میان افزارهای(middleware) سازمانی محبوب است.
8787

8888
ابزار Celery از مکانیسم‌های انتشار/اشتراک (pub/sub) برای انتقال دیتای درونی خود استفاده می‌کند، مانند Redis در ارسال پیام.
8989

@@ -109,14 +109,14 @@
109109
- ماژول asyncio: ماژول داخلی پایتون برای اجرای همزمان چندین کار در یک نخ
110110
- فریمورک django channel: معماری مشابه صف پیام در زمان واقعی برای مدیریت رویدادهای I/O مانند WebSockets
111111

112-
بیایید ابتدا محبوب ترین و قوی ترین راه حل برای اجرای وظایف به صورت ناهمزمان(asynchronous) را درک کنیم: Celey
112+
بیایید ابتدا محبوب ترین و قوی ترین راه حل برای اجرای وظایف به صورت ناهمزمان(asynchronous) را درک کنیم: Celery
113113

114114

115115
## کار کردن با Celery
116116

117-
ابزار Celery یک مدیر صف وظایف ناهمزمان با ویژگی های غنی است. در اینجا، یک وظیفه به یک فراخوانی اشاره دارد که هنگام اجرا، فعالیت را به صورت ناهمزمان انجام می دهد. Celey توسط چندین سازمان معروف از جمله اینستاگرام و موزیلا برای انجام میلیون ها کار در روز در تولید استفاده می شود.
117+
ابزار Celery یک مدیر صف تسک های ناهمزمان با ویژگی های غنی است. در اینجا، یک تسک به یک فراخوانی اشاره دارد که هنگام اجرا، فعالیت را به صورت ناهمزمان انجام می دهد. Celery توسط چندین سازمان معروف از جمله اینستاگرام و موزیلا برای انجام میلیون ها تسک که در طول روز تولید میشوند استفاده می شود.
118118

119-
هنگام نصب Celery، باید اجزای مختلفی مانند broker و جایی برای ذخیره دیتا را انتخاب کنید. اگر گیج شده اید، توصیه می کنم Redis را نصب کنید و برای شروع از مکان دخیره دیتا صرفنظر کنید. از آنجایی که Redis به صورت in-memorty کار می کند، اگر پیام های شما بزرگتر هستند و نیاز به ماندگاری دارند، باید به جای آن از RabbitMQ استفاده کنید. برای شروع می‌توانید مراحل اول با celery و استفاده از celery با جنگو را در راهنمای کاربر celery دنبال کنید.
119+
هنگام نصب Celery، باید اجزای مختلفی مانند broker و جایی برای ذخیره دیتا را انتخاب کنید. اگر گیج شده اید، توصیه می کنم Redis را نصب کنید و برای شروع از مکان ذخیره دیتا صرف نظر کنید. از آنجایی که Redis به صورت in-memorty کار می کند، اگر پیام های شما بزرگتر هستند و نیاز به ماندگاری دارند، باید به جای آن از RabbitMQ استفاده کنید. برای شروع می‌توانید مراحل اول با celery و استفاده از celery با جنگو را در راهنمای کاربر celery دنبال کنید.
120120

121121

122122
در جنگو، تسک های Celery معمولاً در یک فایل جداگانه به نام tasks.py در کنار فایل های یک app می‌آید.
@@ -135,7 +135,7 @@ def fetch_feed(feed_id):
135135
```
136136
این تسک محتوای یک فید RSS را بازیابی کرده و در پایگاه داده ذخیره می کند.
137137

138-
به نظر می رسد یک تابع عادی پایتون است (حتی اگر مربوط به یک کلاس باشد)، جز دکوریتور @shared_task. این یک تسک celery را مشخص می کند. یک تسک مشترک(shared task) می تواند توسط اپ های دیگر در همان پروژه استفاده شود. این کار را با ایجاد نمونه های مستقل از کار در هر برنامه ثبت شده، قابل استفاده مجدد می کند.
138+
به نظر می رسد یک تابع عادی پایتون است (حتی اگر مربوط به یک کلاس باشد)، جز دکوریتور @shared_task. این یک تسک celery را مشخص می کند. یک تسک مشترک(shared task) می تواند توسط اپ های دیگر در همان پروژه استفاده شود. این کار با ایجاد نمونه های مستقل از کار در هر برنامه ثبت شده، قابل استفاده مجدد می کند.
139139

140140
برای فراخوانی این تسک می توانید از متد delay() به صورت زیر استفاده کنید:
141141

@@ -153,7 +153,7 @@ def fetch_feed(feed_id):
153153

154154
![](/08-%20Working%20Asynchronously/images/image-000.png)
155155

156-
زمانی که یک درخواست می رسد، می توان یک Celery task را برای رسیدگی به آن آن فعال کرد.Celery بلافاصله بدون مسدود کردن بقیه درخواست ها یک مقداری برمی‌گردد. در واقع، اجرای کار به پایان نرسیده است، اما یک پیام task وارد یک صف task (یا یکی از بسیاری از صف های موجود) شده است.
156+
زمانی که یک درخواست می رسد، می توان یک Celery task را برای رسیدگی به آن آن فعال کرد.Celery بلافاصله بدون مسدود کردن بقیه درخواست ها یک مقداری برمی‌گردد. در واقع، اجرای کار به پایان نرسیده است، اما یک پیام task وارد یک صف task (یا یکی از از صف های متعدد موجود) شده است.
157157

158158
کارگران سلری(workers) فرآیندهای جداگانه ای هستند که بر صف ها نظارت می کنند که اگر یک task جدید رسید آن ها را اجرا کنند. آن ها انجام یک کار (task) را برعهده میگیرند و یک پیام برگشت (acknowledgment) به صف میفرستند تا این task از صف ما حذف شود. سپس آن task را اجرا کنند پس از انجام این task این فرآیند تکرار می شود و worker یک task جدید را برای اجرا انتخاب می کند.
159159

@@ -171,9 +171,9 @@ def fetch_feed(feed_id):
171171

172172
### Handling failure
173173

174-
هر نوع خطا می تواند هنگام اجرای یک task در Celery اتفاق بیفتند. اگر مکانیزمی برای مدیریت این خطاها نباشد واین خطاها ممکن است شناسایی نشود اغلب، یک کاری که انجام نشود موقتی است، مانند یک API (که خارج از کنترل ما است) یا تمام شدن حافظه. در چنین مواردی، بهتر است صبر کنید و دوباره کار را امتحان کنید.
174+
هر نوع خطا می تواند هنگام اجرای یک task در Celery اتفاق بیفتند. باید مکانیزمی برای مدیریت این خطاها و تلاش مجدد باشد اگر این مکانیزم نباشد این خطاها شناسایی نمی شوند، اگر خطایی در کار رخ دهد موقتی است، مانند یک API (که خارج از کنترل ما است) یا تمام شدن حافظه. در چنین مواردی، بهتر است صبر کرد و دوباره کار را با فاصله های زمانی امتحان کرد.
175175

176-
در Celery، می‌توانید انتخاب کنید که به صورت خودکار یا دستی در صورت خطا دوباره امتحان کند.
176+
در Celery، می‌توانید انتخاب کنید که به صورت خودکار یا دستی در صورت خطا آن تسک را دوباره امتحان کند.
177177
Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد خودکار خود را آسان می کند. در مثال زیر، چندین پارامتر برای تلاش مجدد را مشخص می کنیم:
178178

179179
```python
@@ -191,7 +191,7 @@ Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد
191191

192192
این تکنیک انتظار طولانی‌تر و طولانی‌تر برای تلاش مجدد، exponential backoff نامیده می‌شود. این برای تعامل با یک سرور خارجی ایده آل است زیرا ما به سرور خارجی زمان کافی برای بازیابی می دهیم.
193193

194-
یک نوسان تصادفی برای جلوگیری از مشکلی موسوم به thundering herds اضافه شده است. اگر تعداد زیادی از کارها الگوی تکرار مجدد یکسانی داشته باشند و در همان زمان منبعی را درخواست کنند، ممکن است آن را غیرقابل استفاده کند.
194+
یک نوسان تصادفی(آرگومان jitter) برای جلوگیری از مشکلی موسوم به thundering herds اضافه شده است. اگر تعداد زیادی از کارها الگوی تکرار مجدد یکسانی داشته باشند و در همان زمان منبعی را درخواست کنند، ممکن است آن را غیرقابل استفاده کند.
195195

196196
از این رو، یک عدد تصادفی به دوره انتظار اضافه می شود تا چنین اتفاقاتی رخ ندهد.
197197

@@ -214,7 +214,7 @@ Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد
214214

215215
### تسک های خودتوان
216216

217-
همانطور که دیدیم، کارهای Celery ممکن است چندین بار مجدداً راه اندازی شوند، به خصوص اگر acknowledgment با تاخیر را فعال کرده باشید. این امر کنترل side effect را یک کار را مهم می کند. از این رو، celery توصیه می کند که همه کارها باید خودتوان باشد. خودتوان یک امر ریاضی است
217+
همانطور که دیدیم، کارهای Celery ممکن است چندین بار مجدداً راه اندازی شوند، به خصوص اگر acknowledgment با تاخیر را فعال کرده باشید. این امر کنترل side effect را یک کار مهم می کند. از این رو، celery توصیه می کند که همه کارها باید خودتوان باشد. خودتوان یک امر ریاضی است
218218
ویژگی یک تابع که است که اطمینان می دهد اگر با همان آرگومان ها فراخوانی شود، بدون توجه به اینکه چند بار آن را فراخوانی کنید، همان نتیجه را برمی گرداند.
219219

220220
ممکن است نمونه‌های ساده‌ای از عملکردهای بی‌توان را در خود مستندات Celery دیده باشید، مانند این:
@@ -226,17 +226,17 @@ Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد
226226
```
227227
مهم نیست که چند بار این تابع را فراخوانی کنیم، نتیجه add(2,2) همیشه 4 است.
228228

229-
با این حال، درک تفاوت بین یک عملکرد بی‌توان و عملکردی که عوارض جانبی ندارد (عملکرد خالص یا پوچ) مهم است. عارضه جانبی یک idempotent یکسان خواهد بود، صرف نظر از اینکه یک بار یا چند بار خوانده شده باشد
229+
با این حال، درک تفاوت بین یک تابع خودتوان و تابعی که عوارض جانبی(side effect) ندارد (تابع خالص یا پوچ) مهم است. توابع خودتوان همواره یک عارضه جانبی(side effect) ثابت دارند ، صرف نظر از اینکه یک بار یا چند بار صدا زده شده اند
230230

231-
با این حال درک تفاوت یک یک فانکشن خود توان و یک فانکشن معمولی که side effects ندارد مهم است. موضوع side effects یک فانکشن خودتوان یصرف نظر از اینکه چندبار صدا زده شود یکسان خواهد بود.
231+
با این حال درک تفاوت یک یک فانکشن خود توان و یک فانکشن معمولی که side effects ندارد مهم است. موضوع side effects یک فانکشن خودتوان صرف نظر از اینکه چندبار صدا زده شود یکسان خواهد بود.
232232

233233
برای مثال، تسکی که همیشه هنگام فراخوانی یک آبجکت از نوع order ایجاد می کند، یک فانکشن خودتوان نیست، اما تسکی که یک سفارش موجود را لغو می کند، خودتوان است. عملیات هایی که فقط حالت اشیا را می خوانند و هیچ اثر جانبی(side effect) ندارند، یک فانکشن خودتوان نیستند.
234234

235235
از آنجایی که معماری celery متکی بر تسک های خودتوان است، مهم است که سعی کنید تمام عوارض جانبی یک تسکی که خودتوان نیست را مطالعه کنید و آن را به یک کار غیر خودتوان تبدیل کنید. می‌توانید این کار را با بررسی اینکه آیا تسک ها قبلاً اجرا شده‌اند (اگر اجرا شده‌اند، پس تسک حذف شده است) یا با بررسی اینکه آیا نتیجه تسک در یک آدرس یونیک بر اساس آرگومان‌ها ذخیره شده است یا نه انجام دهید. در قسمت های بعدی کتاب (بخش Avoid writing to shared or global state) یک مثال ازین مورد آورده شده است.
236236

237237
در نتیجه، تسک خود را چندین بار صدا کنید تا بررسی کنید که آیا سیستم شما در همان حالت باقی می ماند یا خیر.
238238

239-
### از نوشتن در دیتابیس در فانکشن هایی به صورت shared یا global خودداری کنید
239+
### از عملیات نوشتن بر روی دیتابیس در فانکشن هایی به صورت shared یا global خودداری کنید
240240

241241
در یک سیستم همزمان، می توانید چندین خواننده داشته باشید. با این حال، لحظه‌ای که نویسندگان زیادی به یک وضعیت مشترک دسترسی پیدا می‌کنند، ممکن است دچار بن بست (deadlocks) یا شرایط رقابتی(race condition) آسیب‌پذیر می‌شوید. برای پرهیز از همه اینها کمی برنامه ریزی و نبوغ لازم است.
242242

@@ -265,7 +265,7 @@ Celery تنظیم دقیق مکانیسم الگوریتم امتحان مجدد
265265

266266
### به روز رسانی پایگاه داده بدون شرایط رقابتی(race condition)
267267

268-
ممکن است با موقعیت‌هایی مواجه شوید که به‌روزرسانی وضعیت مشترک اجتناب‌ناپذیر باشد. اگر دیتابیس شما از قابلیت row-level locks پشتیبانی کند میتوانید ازین مورد یا از اشیا Django F() استفاده کنید قایل ذکر است دیتابیس mysql چون از موتور MyISAM استفاده می کند این قابلیت را پشتیبانی نمی کند.
268+
ممکن است با موقعیت‌هایی مواجه شوید که مجبور باشید یک آبجکت را در یک تابع مشترک (shared function) در دیتابیس به‌روزرسانی کنید. اگر دیتابیس شما از قابلیت row-level locks پشتیبانی کند میتوانید ازین مورد یا از اشیا Django F() استفاده کنید قایل ذکر است دیتابیس mysql چون از موتور MyISAM استفاده می کند این قابلیت را پشتیبانی نمی کند.
269269

270270
از قابلیت row-level locks در جنگو با استفاده از متد select_for_update() در کوئری ست میتوانید استفاده کنید. مثال زیر را ببینید:
271271

@@ -277,8 +277,7 @@ with transaction.atomic():
277277
feed.save()
278278
```
279279

280-
با استفاده از select_for_update() ما سطر های آبجکت Feed اصطلاحا قفل (lock) میکند که تا زمانی که ترنزکشن ما تمام نشد اجازه ایجاد و تغییر در دیتابیس نداشته باشیم.
281-
280+
با استفاده از select_for_update() سطر های آبجکت Feed اصطلاحا قفل (lock) میشود که تا زمانی که ترنزکشن ما تمام نشد اجازه ایجاد و تغییر در دیتابیس نداشته باشیم.
282281
اگر نخ یا فرآیند دیگری قبلاً همان ردیف را قفل کرده باشد، کوئری منتظر می ماند یا کوِئری تا زمانی که lock در دیتابیس تمام شود مسدود می شود. این رفتار را می توان با استفاده از پارامترهای کلمه کلیدی select_for_update تغییر داد تا یک خطا ایجاد کند یا در صورت قفل از آن رد شود.
283282

284283
اگر عملیات روی یک فیلد را بتوان در دیتابیس انجام داد بهتر است از فانکشن F() برای جلوگیری از شرایط رقابتی(race condition) استفاده شود. فانکشن F() از گرفتن دیتا از دیتابیس و انتقال به مموری پایتون برای انجامیک عملیات جلوگیری می کند و این کار را مستقیم بر روی دیتابیس انجام می دهد. به مثال زیر توجه کنید:

0 commit comments

Comments
 (0)