عنوان:

‫چالش‌های متداول توسعه‌دهندگان ASP.NET Core هنگام استفاده از Nginx - قسمت دوم - مدیریت فرآیند و سرویس‌ها


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۴/۰۸ ۰۸:۱۰
آدرس: www.dntips.ir
در قسمت قبل، با موفقیت برنامه را روی سرور اجرا کردیم اما با یک مشکل بزرگ روبرو شدیم: برنامه ما شکننده است. اگر ترمینال را ببندیم یا سرور ریبوت شود، سایت ما از دسترس خارج می‌شود. این روش برای محیط پروداکشن به هیچ وجه قابل قبول نیست. در این قسمت، یاد می‌گیریم که چگونه برنامه ASP.NET Core خود را به یک سرویس (Service) واقعی در لینوکس تبدیل کنیم. ما از systemd، سیستم مدیریت سرویس استاندارد در اکثر توزیع‌های مدرن لینوکس (مانند اوبونتو، CentOS، Debian)، استفاده خواهیم کرد تا برنامه ما به صورت خودکار اجرا، مدیریت و در صورت نیاز، راه‌اندازی مجدد شود.

بخش ۱: چرا به یک سرویس نیاز داریم؟ معرفی systemd
systemd مدیر سیستم و سرویس‌ها در لینوکس است. وقتی برنامه خود را به عنوان یک سرویس به systemd معرفی می‌کنید، وظیفه مدیریت چرخه حیات (Lifecycle) آن را به سیستم‌عامل می‌سپارید.
مزایای کلیدی استفاده از systemd:
  • اجرای خودکار پس از بوت: دیگر نیازی نیست پس از هر بار ریبوت شدن سرور، به صورت دستی برنامه را اجرا کنید.
  • راه‌اندازی مجدد خودکار (Auto-Restart): اگر برنامه شما به هر دلیلی (مانند یک باگ یا کمبود حافظه) Crash کند، systemd فوراً آن را مجدداً اجرا می‌کند.
  • مدیریت متمرکز: با دستورات استاندارد و ساده (start, stop, restart, status) می‌توانید سرویس خود را کنترل کنید.
  • امنیت: می‌توانید مشخص کنید که سرویس با چه کاربری اجرا شود. اجرای برنامه با کاربر root یک ریسک امنیتی بزرگ است.
  • لاگ‌برداری متمرکز: تمام خروجی‌های استاندارد (Console Logs) برنامه شما به صورت خودکار توسط journald (سرویس لاگ systemd) جمع‌آوری می‌شود.

بخش ۲: ساخت فایل سرویس systemd قدم به قدم
بیایید یک فایل سرویس برای برنامه خود بسازیم. نام برنامه را MyWebApp فرض می‌کنیم.
قدم ۱: ایجاد فایل سرویس
فایل‌های سرویس در مسیر /etc/systemd/system/ قرار می‌گیرند و باید پسوند .service داشته باشند. با یک ویرایشگر متن (مانند nano یا vim) فایل را ایجاد کنید:
sudo nano /etc/systemd/system/kestrel-mywebapp.service

قدم ۲: نوشتن محتوای فایل سرویس
محتوای زیر یک قالب استاندارد و بسیار کارآمد است. آن را در فایلی که ایجاد کردید کپی کرده و سپس بخش‌های مختلف آن را با هم بررسی می‌کنیم.
[Unit]
Description=My Awesome ASP.NET Core Web App

[Service]
# مسیر پوشه‌ای که فایل‌های برنامه در آن قرار دارند
WorkingDirectory=/var/www/mywebapp

# دستور اصلی برای اجرای برنامه. حتما از مسیر کامل dotnet استفاده کنید
ExecStart=/usr/bin/dotnet /var/www/mywebapp/MyWebApp.dll

# راه‌اندازی مجدد خودکار در صورت شکست
Restart=always
# تاخیر ۱۰ ثانیه‌ای قبل از راه‌اندازی مجدد
RestartSec=10

# سیگنال استاندارد برای خاموش کردن نرم برنامه
KillSignal=SIGINT

# یک شناسه برای لاگ‌های برنامه در syslog
SyslogIdentifier=mywebapp

# کاربری که برنامه با دسترسی آن اجرا می‌شود (بسیار مهم)
User=www-data

# تنظیم متغیرهای محیطی، مهم‌ترین آن برای محیط پروداکشن
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target
تحلیل بخش‌های مختلف فایل سرویس:
[Unit]:
  • Description: یک توضیح کوتاه و خوانا برای سرویس شما.

[Service]: این بخش قلب تنظیمات ماست.
  • WorkingDirectory: (راه حل مشکل مسیرهای نسبی) این دستور به systemd می‌گوید که قبل از اجرای برنامه، به این پوشه برود. این کار باعث می‌شود برنامه شما فایل‌هایی مانند appsettings.json یا دیتابیس SQLite را به درستی پیدا کند.
  • ExecStart: دستوری که باید برای شروع برنامه اجرا شود. همیشه از مسیرهای مطلق (کامل) برای dotnet و فایل DLL برنامه خود استفاده کنید.
  • Restart=always: تضمین می‌کند که اگر برنامه به هر دلیلی بسته شد، systemd آن را دوباره اجرا کند.
  • User=www-data: (راه حل مشکل امنیتی) مشخص می‌کند که برنامه با کاربر www-data اجرا شود، نه root. کاربر www-data معمولاً توسط Nginx استفاده می‌شود و دسترسی‌های محدودی دارد که امنیت را افزایش می‌دهد.
  • Environment: برای تنظیم متغیرهای محیطی استفاده می‌شود. تنظیم ASPNETCORE_ENVIRONMENT=Production باعث می‌شود برنامه شما در حالت بهینه و امن اجرا شود و تنظیمات داخل appsettings.Production.json را بخواند.

[Install]:
  • WantedBy=multi-user.target: این خط به systemd می‌گوید که این سرویس باید هنگام بوت شدن سیستم در حالت چندکاربره فعال شود.

قدم ۳: مدیریت سرویس با systemctl
پس از ذخیره کردن فایل، باید از دستورات systemctl برای مدیریت آن استفاده کنید:
بارگذاری مجدد systemd: به systemd بگویید تا فایل جدید شما را بخواند.
sudo systemctl daemon-reload
فعال‌سازی سرویس: سرویس را طوری تنظیم کنید که با هر بار بوت شدن سیستم، خودکار اجرا شود.
sudo systemctl enable kestrel-mywebapp.service
شروع به کار سرویس: سرویس را همین حالا استارت بزنید.
sudo systemctl start kestrel-mywebapp.service
بررسی وضعیت سرویس: مهم‌ترین دستور برای عیب‌یابی!
sudo systemctl status kestrel-mywebapp.service
اگر همه چیز درست باشد، باید خروجی سبز رنگ active (running) را مشاهده کنید.

بخش ۳: عیب‌یابی مشکلات رایج سرویس
مشکل شماره ۱: سرویس اجرا نمی‌شود و status وضعیت failed را نشان می‌دهد
علامت:systemctl status یک خروجی قرمز رنگ با وضعیت failed یا inactive (dead) را نمایش می‌دهد.
دلایل و راه‌حل‌ها:
مشکل دسترسی (Permission Denied):
  • علت: کاربری که در فایل سرویس تعریف کرده‌اید (www-data)، اجازه خواندن و اجرای فایل‌های برنامه در پوشه WorkingDirectory را ندارد.
  • راه‌حل: مالکیت پوشه برنامه را به کاربر مورد نظر تغییر دهید.
# تغییر مالکیت کل پوشه و فایل‌های آن به کاربر و گروه www-data
sudo chown -R www-data:www-data /var/www/mywebapp

# اطمینان از اینکه فایل‌ها دسترسی‌های صحیح را دارند
sudo chmod -R 755 /var/www/mywebapp
اشتباه در مسیرها:
  • علت: مسیر WorkingDirectory یا ExecStart در فایل .service اشتباه است.
  • راه‌حل: مسیرها را با دقت دوباره چک کنید و مطمئن شوید کاملاً صحیح و مطلق هستند.

مشکل شماره ۲: برنامه اجرا نمی‌شود و نمی‌دانم چرا! (مشاهده لاگ‌ها)
وقتی برنامه شما به عنوان سرویس اجرا می‌شود، دیگر خروجی آن را در ترمینال نمی‌بینید. پس چگونه خطاها را پیدا کنیم؟
راه‌حل: استفاده از journalctl
این دستور، دفترچه گزارشات systemd است و تمام خروجی‌های کنسول برنامه شما را ضبط می‌کند.
مشاهده لاگ‌های سرویس:
sudo journalctl -u kestrel-mywebapp.service
  • این دستور تمام لاگ‌های مربوط به سرویس شما از ابتدا تا کنون را نشان می‌دهد. هر خطایی که در حالت عادی در کنسول می‌دیدید، اینجا ثبت شده است.

دستورات کاربردی journalctl:
  • برای دنبال کردن لاگ‌ها به صورت زنده (بسیار مفید برای دیباگ):
sudo journalctl -u kestrel-mywebapp.service -f
  • برای دیدن فقط ۱۰۰ خط آخر لاگ‌ها:
sudo journalctl -u kestrel-mywebapp.service -n 100
  • برای پریدن به انتهای لاگ‌ها و دیدن آخرین خطاها:
sudo journalctl -u kestrel-mywebapp.service -e

جمع‌بندی فصل ۲:
تبریک می‌گویم! شما با موفقیت برنامه ASP.NET Core خود را از یک اسکریپت شکننده به یک سرویس قوی و پایدار تبدیل کردید که به صورت خودکار مدیریت می‌شود. همچنین یاد گرفتید که چگونه با استفاده از systemctl و journalctl آن را کنترل و عیب‌یابی کنید.
اکنون که از پایداری برنامه خود در پشت صحنه مطمئن هستیم، در قسمت بعدی به خط مقدم بازمی‌گردیم و Nginx را به طور کامل پیکربندی می‌کنیم تا به شکل صحیح و امن، ترافیک را به این سرویس جدید هدایت کند.
مطالب مشابه