کاوشی عمیق در تورنادو، یک فریمورک وب پایتون و کتابخانه شبکهسازی ناهمزمان. یاد بگیرید چگونه با توضیحات دقیق، مثالها و بهترین شیوهها، برنامههای مقیاسپذیر و با کارایی بالا بسازید.
مستندات تورنادو: راهنمای جامع برای توسعهدهندگان در سراسر جهان
تورنادو یک فریمورک وب پایتون و کتابخانه شبکهسازی ناهمزمان است که در اصل در FriendFeed توسعه یافته است. این فریمورک به ویژه برای long-polling، وبسوکتها و سایر برنامههایی که نیاز به اتصال طولانیمدت به هر کاربر دارند، مناسب است. ورودی/خروجی شبکه غیرمسدودکننده آن، آن را بسیار مقیاسپذیر و گزینهای قدرتمند برای ساخت برنامههای وب با کارایی بالا میکند. این راهنمای جامع شما را با مفاهیم اصلی تورنادو آشنا کرده و مثالهای عملی برای شروع کار ارائه میدهد.
تورنادو چیست؟
در هسته خود، تورنادو یک فریمورک وب و کتابخانه شبکهسازی ناهمزمان است. برخلاف فریمورکهای وب همزمان سنتی، تورنادو از معماری تک-نخی و مبتنی بر حلقه رویداد استفاده میکند. این بدان معناست که میتواند اتصالات همزمان زیادی را بدون نیاز به یک نخ برای هر اتصال مدیریت کند، که آن را کارآمدتر و مقیاسپذیرتر میسازد.
ویژگیهای کلیدی تورنادو:
- شبکهسازی ناهمزمان: هسته تورنادو بر پایه ورودی/خروجی ناهمزمان ساخته شده است که به آن اجازه میدهد هزاران اتصال همزمان را به طور کارآمد مدیریت کند.
- فریمورک وب: این فریمورک شامل ویژگیهایی مانند مدیریتکنندههای درخواست، مسیریابی، قالببندی و احراز هویت است که آن را به یک فریمورک وب کامل تبدیل میکند.
- پشتیبانی از وبسوکت: تورنادو پشتیبانی بسیار خوبی از وبسوکتها فراهم میکند که ارتباط بیدرنگ بین سرور و کلاینتها را امکانپذیر میسازد.
- سبک و سریع: تورنادو که برای کارایی طراحی شده، سبک و کارآمد است و سربار را به حداقل رسانده و توان عملیاتی را به حداکثر میرساند.
- آسان برای استفاده: با وجود ویژگیهای پیشرفته، یادگیری و استفاده از تورنادو با یک API واضح و مستند، نسبتاً آسان است.
راهاندازی محیط تورنادو
قبل از شروع توسعه با تورنادو، باید محیط خود را راهاندازی کنید. در اینجا یک راهنمای گام به گام آورده شده است:
- نصب پایتون: مطمئن شوید که پایتون 3.6 یا بالاتر را نصب کردهاید. میتوانید آن را از وبسایت رسمی پایتون (python.org) دانلود کنید.
- ایجاد یک محیط مجازی (توصیه میشود): از
venv
یاvirtualenv
برای ایجاد یک محیط ایزوله برای پروژه خود استفاده کنید:python3 -m venv myenv source myenv/bin/activate # در لینوکس/macOS myenv\Scripts\activate # در ویندوز
- نصب تورنادو: تورنادو را با استفاده از pip نصب کنید:
pip install tornado
اولین برنامه تورنادو شما
بیایید یک برنامه ساده "Hello, World!" با تورنادو ایجاد کنیم. فایلی به نام app.py
ایجاد کرده و کد زیر را به آن اضافه کنید:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, World!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
اکنون، برنامه را از ترمینال خود اجرا کنید:
python app.py
مرورگر وب خود را باز کرده و به http://localhost:8888
بروید. باید پیام "Hello, World!" را ببینید.
توضیحات:
tornado.ioloop
: حلقه رویداد اصلی که عملیات ناهمزمان را مدیریت میکند.tornado.web
: اجزای فریمورک وب مانند مدیریتکنندههای درخواست و مسیریابی را فراهم میکند.MainHandler
: یک مدیریتکننده درخواست که نحوه رسیدگی به درخواستهای HTTP ورودی را تعریف میکند. متدget()
برای درخواستهای GET فراخوانی میشود.tornado.web.Application
: برنامه تورنادو را ایجاد میکند و الگوهای URL را به مدیریتکنندههای درخواست نگاشت میکند.app.listen(8888)
: سرور را راهاندازی کرده و برای اتصالات ورودی روی پورت 8888 گوش میدهد.tornado.ioloop.IOLoop.current().start()
: حلقه رویداد را شروع میکند که درخواستهای ورودی را پردازش کرده و عملیات ناهمزمان را مدیریت میکند.
مدیریتکنندههای درخواست و مسیریابی
مدیریتکنندههای درخواست، اساس برنامههای وب تورنادو هستند. آنها نحوه رسیدگی به درخواستهای HTTP ورودی را بر اساس URL تعریف میکنند. مسیریابی، URLها را به مدیریتکنندههای درخواست خاص نگاشت میکند.
تعریف مدیریتکنندههای درخواست:
برای ایجاد یک مدیریتکننده درخواست، از tornado.web.RequestHandler
ارثبری کرده و متدهای HTTP مناسب (get
، post
، put
، delete
و غیره) را پیادهسازی کنید.
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("This is a GET request.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Received POST data: {data}")
مسیریابی:
مسیریابی هنگام ایجاد tornado.web.Application
پیکربندی میشود. شما لیستی از تاپلها را ارائه میدهید که هر تاپل شامل یک الگوی URL و مدیریتکننده درخواست مربوطه است.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
الگوهای URL:
الگوهای URL عبارات منظم هستند. میتوانید از گروههای عبارات منظم برای گرفتن بخشهایی از URL و ارسال آنها به عنوان آرگومان به متدهای مدیریتکننده درخواست استفاده کنید.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"User ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
در این مثال، /user/([0-9]+)
با URLهایی مانند /user/123
مطابقت دارد. بخش ([0-9]+)
یک یا چند رقم را گرفته و آنها را به عنوان آرگومان user_id
به متد get
از UserHandler
ارسال میکند.
قالببندی (Templating)
تورنادو شامل یک موتور قالببندی ساده و کارآمد است. قالبها برای تولید پویای HTML استفاده میشوند و منطق نمایش را از منطق برنامه جدا میکنند.
ایجاد قالبها:
قالبها معمولاً در فایلهای جداگانه (مثلاً index.html
) ذخیره میشوند. در اینجا یک مثال ساده آورده شده است:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome, {{ name }}!</h1>
<p>Today is {{ today }}.</p>
</body>
</html>
{{ name }}
و {{ today }}
متغیرهای جایگزینی هستند که با مقادیر واقعی هنگام رندر شدن قالب جایگزین میشوند.
رندر کردن قالبها:
برای رندر کردن یک قالب، از متد render()
در مدیریتکننده درخواست خود استفاده کنید:
class TemplateHandler(tornado.web.RequestHandler):
def get(self):
name = "John Doe"
today = "2023-10-27"
self.render("index.html", name=name, today=today)
مطمئن شوید که تنظیم template_path
در تنظیمات برنامه شما به درستی پیکربندی شده باشد. به طور پیشفرض، تورنادو به دنبال قالبها در پوشهای به نام templates
در همان دایرکتوری فایل برنامه شما میگردد.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
سینتکس قالب:
قالبهای تورنادو از ویژگیهای مختلفی پشتیبانی میکنند، از جمله:
- متغیرها:
{{ variable }}
- جریان کنترل:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- توابع:
{{ function(argument) }}
- الحاقها (Includes):
{% include "another_template.html" %}
- گریز از کاراکترها (Escaping): تورنادو به طور خودکار موجودیتهای HTML را برای جلوگیری از حملات اسکریپتنویسی بین سایتی (XSS) گریز میدهد. میتوانید گریز را با استفاده از
{% raw variable %}
غیرفعال کنید.
عملیات ناهمزمان
قدرت تورنادو در قابلیتهای ناهمزمان آن نهفته است. عملیات ناهمزمان به برنامه شما اجازه میدهد تا ورودی/خروجی غیرمسدودکننده انجام دهد و کارایی و مقیاسپذیری را بهبود بخشد. این امر به ویژه برای کارهایی که شامل انتظار برای منابع خارجی مانند کوئریهای پایگاه داده یا درخواستهای شبکه است، مفید میباشد.
@tornado.gen.coroutine
:
دکوراتور @tornado.gen.coroutine
به شما اجازه میدهد تا کد ناهمزمان را با استفاده از کلمه کلیدی yield
بنویسید. این کار باعث میشود کد ناهمزمان بیشتر شبیه به کد همزمان به نظر برسد و رفتار کند، که خوانایی و قابلیت نگهداری را بهبود میبخشد.
import tornado.gen
import tornado.httpclient
class AsyncHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
http_client = tornado.httpclient.AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
self.write(response.body.decode('utf-8'))
در این مثال، http_client.fetch()
یک عملیات ناهمزمان است که یک Future
را برمیگرداند. کلمه کلیدی yield
اجرای کوروتین را تا زمان حل شدن Future
به حالت تعلیق در میآورد. پس از حل شدن Future
، کوروتین از سر گرفته شده و بدنه پاسخ به کلاینت نوشته میشود.
tornado.concurrent.Future
:
یک Future
نتیجه یک عملیات ناهمزمان را نشان میدهد که ممکن است هنوز در دسترس نباشد. میتوانید از اشیاء Future
برای زنجیر کردن عملیات ناهمزمان به یکدیگر و مدیریت خطاها استفاده کنید.
tornado.ioloop.IOLoop
:
IOLoop
قلب موتور ناهمزمان تورنادو است. این حلقه توصیفگرهای فایل و سوکتها را برای رویدادها نظارت کرده و آنها را به مدیریتکنندههای مناسب ارسال میکند. معمولاً نیازی به تعامل مستقیم با IOLoop
ندارید، اما درک نقش آن در مدیریت عملیات ناهمزمان مهم است.
وبسوکتها (WebSockets)
تورنادو پشتیبانی بسیار خوبی از وبسوکتها فراهم میکند که ارتباط بیدرنگ بین سرور و کلاینتها را امکانپذیر میسازد. وبسوکتها برای برنامههایی که نیاز به ارتباط دوطرفه و با تأخیر کم دارند، مانند برنامههای چت، بازیهای آنلاین و داشبوردهای بیدرنگ، ایدهآل هستند.
ایجاد یک مدیریتکننده وبسوکت:
برای ایجاد یک مدیریتکننده وبسوکت، از tornado.websocket.WebSocketHandler
ارثبری کرده و متدهای زیر را پیادهسازی کنید:
open()
: هنگامی که یک اتصال وبسوکت جدید برقرار میشود، فراخوانی میشود.on_message(message)
: هنگامی که پیامی از کلاینت دریافت میشود، فراخوانی میشود.on_close()
: هنگامی که اتصال وبسوکت بسته میشود، فراخوانی میشود.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")
def on_message(self, message):
self.write_message(f"You sent: {message}")
def on_close(self):
print("WebSocket closed")
def check_origin(self, origin):
return True # فعال کردن اتصالات وبسوکت بین مبدأ
ادغام وبسوکتها در برنامه شما:
مدیریتکننده وبسوکت را به پیکربندی مسیریابی برنامه خود اضافه کنید:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
پیادهسازی سمت کلاینت:
در سمت کلاینت، میتوانید از جاوا اسکریپت برای برقراری اتصال وبسوکت و ارسال/دریافت پیامها استفاده کنید:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("WebSocket connection established");
websocket.send("Hello from the client!");
};
websocket.onmessage = (event) => {
console.log("Received message:", event.data);
};
websocket.onclose = () => {
console.log("WebSocket connection closed");
};
احراز هویت و امنیت
امنیت یک جنبه حیاتی در توسعه برنامههای وب است. تورنادو چندین ویژگی برای کمک به شما در ایمنسازی برنامههایتان فراهم میکند، از جمله احراز هویت، اعطای دسترسی و محافظت در برابر آسیبپذیریهای رایج وب.
احراز هویت:
احراز هویت فرآیند تأیید هویت یک کاربر است. تورنادو پشتیبانی داخلی برای طرحهای مختلف احراز هویت فراهم میکند، از جمله:
- احراز هویت مبتنی بر کوکی: ذخیره اطلاعات کاربری در کوکیها.
- احراز هویت شخص ثالث (OAuth): ادغام با پلتفرمهای رسانههای اجتماعی محبوب مانند گوگل، فیسبوک و توییتر.
- کلیدهای API: استفاده از کلیدهای API برای احراز هویت درخواستهای API.
اعطای دسترسی (Authorization):
اعطای دسترسی فرآیند تعیین اینکه آیا یک کاربر اجازه دسترسی به یک منبع خاص را دارد یا خیر است. شما میتوانید منطق اعطای دسترسی را در مدیریتکنندههای درخواست خود برای محدود کردن دسترسی بر اساس نقشها یا مجوزهای کاربر پیادهسازی کنید.
بهترین شیوههای امنیتی:
- محافظت در برابر اسکریپتنویسی بین سایتی (XSS): تورنادو به طور خودکار موجودیتهای HTML را برای جلوگیری از حملات XSS گریز میدهد. همیشه از متد
render()
برای رندر کردن قالبها استفاده کنید و از تولید مستقیم HTML در مدیریتکنندههای درخواست خود خودداری کنید. - محافظت در برابر جعل درخواست بین سایتی (CSRF): محافظت CSRF را در تنظیمات برنامه خود فعال کنید تا از حملات CSRF جلوگیری شود.
- HTTPS: همیشه از HTTPS برای رمزگذاری ارتباط بین سرور و کلاینتها استفاده کنید.
- اعتبارسنجی ورودی: تمام ورودیهای کاربر را برای جلوگیری از حملات تزریق و سایر آسیبپذیریها اعتبارسنجی کنید.
- ممیزیهای امنیتی منظم: ممیزیهای امنیتی منظم را برای شناسایی و رفع آسیبپذیریهای بالقوه انجام دهید.
استقرار (Deployment)
استقرار یک برنامه تورنادو شامل چندین مرحله است، از جمله پیکربندی یک وب سرور، راهاندازی یک مدیر فرآیند و بهینهسازی عملکرد.
وب سرور:
میتوانید تورنادو را پشت یک وب سرور مانند Nginx یا Apache مستقر کنید. وب سرور به عنوان یک پراکسی معکوس عمل کرده و درخواستهای ورودی را به برنامه تورنادو ارسال میکند.
مدیر فرآیند:
یک مدیر فرآیند مانند Supervisor یا systemd میتواند برای مدیریت فرآیند تورنادو استفاده شود و اطمینان حاصل کند که در صورت خرابی به طور خودکار راهاندازی مجدد میشود.
بهینهسازی عملکرد:
- استفاده از یک حلقه رویداد آماده برای تولید: برای بهبود عملکرد از یک حلقه رویداد آماده برای تولید مانند
uvloop
استفاده کنید. - فعال کردن فشردهسازی gzip: فشردهسازی gzip را برای کاهش حجم پاسخهای HTTP فعال کنید.
- کش کردن فایلهای استاتیک: فایلهای استاتیک را برای کاهش بار روی سرور کش کنید.
- نظارت بر عملکرد: عملکرد برنامه خود را با استفاده از ابزارهایی مانند New Relic یا Prometheus نظارت کنید.
بینالمللیسازی (i18n) و محلیسازی (l10n)
هنگام ساخت برنامهها برای مخاطبان جهانی، مهم است که بینالمللیسازی (i18n) و محلیسازی (l10n) را در نظر بگیرید. i18n فرآیند طراحی یک برنامه به گونهای است که بتوان آن را بدون تغییرات مهندسی با زبانها و مناطق مختلف تطبیق داد. l10n فرآیند تطبیق یک برنامه بینالمللی شده برای یک زبان یا منطقه خاص با افزودن اجزای محلی و ترجمه متن است.
تورنادو و i18n/l10n
تورنادو به خودی خود کتابخانههای داخلی i18n/l10n ندارد. با این حال، شما میتوانید به راحتی کتابخانههای استاندارد پایتون مانند `gettext` یا فریمورکهای پیچیدهتری مانند Babel را برای مدیریت i18n/l10n در برنامه تورنادوی خود ادغام کنید.
مثال با استفاده از `gettext`:
1. **راهاندازی localeهای خود:** برای هر زبانی که میخواهید پشتیبانی کنید، دایرکتوریهایی حاوی کاتالوگهای پیام (معمولاً فایلهای `.mo`) ایجاد کنید.
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **استخراج رشتههای قابل ترجمه:** از ابزاری مانند `xgettext` برای استخراج رشتههای قابل ترجمه از کد پایتون خود به یک فایل `.po` (Portable Object) استفاده کنید. این فایل حاوی رشتههای اصلی و جایگزینهایی برای ترجمهها خواهد بود.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **ترجمه رشتهها:** رشتهها را در فایلهای `.po` برای هر زبان ترجمه کنید.
4. **کامپایل کردن ترجمهها:** فایلهای `.po` را به فایلهای `.mo` (Machine Object) کامپایل کنید که توسط `gettext` در زمان اجرا استفاده میشوند.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **ادغام در برنامه تورنادوی شما:**
import gettext
import locale
import os
import tornado.web
class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
try:
locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
except locale.Error:
# مدیریت مواردی که locale توسط سیستم پشتیبانی نمیشود
print(f"Locale {self.get_user_locale().code} not supported")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# منطق برای تعیین locale کاربر (مثلاً از هدر Accept-Language، تنظیمات کاربر و غیره)
# این یک مثال ساده است - شما به یک راهحل قویتر نیاز خواهید داشت
accept_language = self.request.headers.get('Accept-Language', 'en')
return tornado.locale.get(accept_language.split(',')[0].split(';')[0])
class MainHandler(BaseHandler):
def get(self):
self.render("index.html", _=self._)
settings = {
"template_path": os.path.join(os.path.dirname(__file__), "templates"),
}
app = tornado.web.Application([
(r"/", MainHandler),
], **settings)
6. **اصلاح قالبهای خود:** از تابع `_()` (که به `gettext.gettext` متصل است) برای علامتگذاری رشتهها برای ترجمه در قالبهای خود استفاده کنید.
<h1>{{ _("Welcome to our website!") }}</h1>
<p>{{ _("This is a translated paragraph.") }}</p>
ملاحظات مهم برای مخاطبان جهانی:
- **کدبندی کاراکترها:** همیشه از کدبندی UTF-8 برای پشتیبانی از طیف گستردهای از کاراکترها استفاده کنید.
- **قالببندی تاریخ و زمان:** از قالببندی تاریخ و زمان مختص هر locale استفاده کنید. توابع `strftime` و `strptime` پایتون میتوانند با تنظیمات locale استفاده شوند.
- **قالببندی اعداد:** از قالببندی اعداد مختص هر locale (مثلاً جداکنندههای اعشاری، جداکنندههای هزارگان) استفاده کنید. ماژول `locale` توابعی برای این کار فراهم میکند.
- **قالببندی ارز:** از قالببندی ارز مختص هر locale استفاده کنید. برای مدیریت پیشرفتهتر ارز، استفاده از کتابخانهای مانند `Babel` را در نظر بگیرید.
- **زبانهای راست به چپ (RTL):** از زبانهای RTL مانند عربی و عبری پشتیبانی کنید. این ممکن است شامل آینهای کردن چیدمان وبسایت شما باشد.
- **کیفیت ترجمه:** از مترجمان حرفهای برای اطمینان از ترجمههای دقیق و مناسب فرهنگی استفاده کنید. ترجمه ماشینی میتواند نقطه شروع خوبی باشد، اما اغلب نیاز به بازبینی انسانی دارد.
- **تشخیص locale کاربر:** تشخیص قوی locale را بر اساس ترجیحات کاربر، تنظیمات مرورگر یا آدرس IP پیادهسازی کنید. راهی برای کاربران فراهم کنید تا زبان مورد نظر خود را به صورت دستی انتخاب کنند.
- **تست:** برنامه خود را با localeهای مختلف به طور کامل تست کنید تا اطمینان حاصل شود که همه چیز به درستی نمایش داده میشود.
مباحث پیشرفته
صفحات خطای سفارشی:
میتوانید صفحات خطایی را که تورنادو هنگام بروز خطا نمایش میدهد، سفارشی کنید. این به شما امکان میدهد تجربه کاربرپسندتری ارائه دهید و اطلاعات اشکالزدایی را شامل شوید.
تنظیمات سفارشی:
میتوانید تنظیمات سفارشی را در پیکربندی برنامه خود تعریف کرده و در مدیریتکنندههای درخواست خود به آنها دسترسی داشته باشید. این برای ذخیره پارامترهای خاص برنامه، مانند رشتههای اتصال پایگاه داده یا کلیدهای API، مفید است.
تست:
برنامههای تورنادوی خود را به طور کامل تست کنید تا اطمینان حاصل شود که به درستی و ایمن کار میکنند. از تستهای واحد، تستهای یکپارچهسازی و تستهای سرتاسری برای پوشش دادن تمام جنبههای برنامه خود استفاده کنید.
نتیجهگیری
تورنادو یک فریمورک وب قدرتمند و همهکاره است که برای ساخت برنامههای وب مقیاسپذیر و با کارایی بالا بسیار مناسب است. معماری ناهمزمان آن، پشتیبانی از وبسوکت و API با کاربری آسان، آن را به گزینهای محبوب برای توسعهدهندگان در سراسر جهان تبدیل کرده است. با دنبال کردن دستورالعملها و مثالهای این راهنمای جامع، میتوانید ساخت برنامههای تورنادوی خود را شروع کرده و از ویژگیهای متعدد آن بهرهمند شوید.
به یاد داشته باشید که برای بهروزترین اطلاعات و بهترین شیوهها، به مستندات رسمی تورنادو مراجعه کنید. کدنویسی خوشی داشته باشید!