در ادامهی سری کار با
nginx، نیاز است با نحوهی عیبیابی و رفع مشکلات مرتبط با آن نیز آشنا شویم تا بتوانیم بدون ترس و لرز، برنامههای خود را بر روی لینوکس توزیع کرده و همچنین پشتیبانی و نگهداری کنیم. در این قسمت، اولین و مهمترین قدمها برای انتشار یک برنامه ASP.NET Core روی سرور لینوکس با استفاده از Nginx را بررسی میکنیم. بسیاری از توسعهدهندگان در این مرحله با خطاهایی مواجه میشوند که ساعتها وقتشان را میگیرد. هدف ما در این فصل، درک معماری صحیح، آشنایی با تنظیمات اولیه و توانایی عیبیابی سریع شایعترین مشکلات است.
بخش ۱: درک معماری - چرا به Nginx در کنار Kestrel نیاز داریم؟
وقتی شما یک برنامه ASP.NET Core را اجرا میکنید، وبسرور داخلی به نام Kestrel مسئول اجرای کد شما و پاسخ به درخواستهای HTTP میشود. Kestrel بسیار سریع و بهینه است، اما برای قرار گرفتن مستقیم در معرض اینترنت طراحی نشده است. در محیط پروداکشن، ما به یک Reverse Proxy قدرتمند مانند Nginx نیاز داریم.
نقشها در این معماری:
Kestrel:
- وب سرور اپلیکیشن شماست.
- کد #C شما را اجرا کرده و صفحات داینامیک را تولید میکند.
- به صورت پیشفرض روی یک پورت غیر استاندارد (مانند 5000) و فقط روی
localhost اجرا میشود تا از بیرون سرور مستقیماً قابل دسترسی نباشد.
Nginx:
- در خط مقدم قرار دارد و درخواستهای کاربران را از اینترنت دریافت میکند.
- مانند یک نگهبان و توزیعکننده عمل میکند.
- وظایف اصلی آن عبارتند از:
- Reverse Proxy: درخواستهای معتبر را به سمت Kestrel هدایت (Forward) میکند.
- SSL Termination: مسئولیت مدیریت HTTPS و رمزنگاری را بر عهده میگیرد.
- Serving Static Files: فایلهای ثابت (CSS, JS, تصاویر) را مستقیماً و با سرعت بالا سرو میکند.
- Caching: میتواند پاسخها را کش کند تا بار روی Kestrel کاهش یابد.
- Load Balancing: در معماریهای بزرگتر، میتواند ترافیک را بین چند نمونه از برنامه شما تقسیم کند.
جریان یک درخواست (Request Flow):
کاربر (مرورگر) -> اینترنت -> (پورت 80/443) Nginx -> (پورت 5000) Kestrel -> برنامه ASP.NET Core شما
بخش ۲: مشکلات متداول در راهاندازی اولیه و راهحلها
در این بخش به سراغ خطاهایی میرویم که تقریباً هر توسعهدهندهای در اولین تلاش خود با آنها روبرو میشود.
مشکل شماره ۱: خطای معروف 502 Bad Gateway
این خطا پرتکرارترین مشکلی است که با آن مواجه خواهید شد. خطای 502 به این معناست که Nginx (نگهبان) توانسته درخواست را دریافت کند، اما نتوانسته آن را به Kestrel (برنامه اصلی) برساند یا پاسخی از آن دریافت کند.
دلایل احتمالی:
- برنامه ASP.NET Core شما اصلاً در حال اجرا نیست: این شایعترین دلیل است.
- برنامه ASP.NET Core در حین اجرا Crash کرده است: به دلیل یک خطا در کد، برنامه متوقف شده است.
- فایروال سرور لینوکس پورت را مسدود کرده است: Nginx نمیتواند با Kestrel روی پورت مورد نظر (مثلاً 5000) ارتباط برقرار کند.
- آدرس یا پورت در فایل کانفیگ Nginx اشتباه است:
proxy_pass به آدرس یا پورت اشتباهی اشاره میکند. - مشکلات SELinux یا AppArmor: سیستمهای امنیتی لینوکس ممکن است جلوی ارتباط شبکه بین Nginx و Kestrel را بگیرند (موردی پیشرفتهتر).
راهحل و عیبیابی:
قدم اول: وضعیت برنامه را چک کنید.
- وارد سرور خود شوید و دستور زیر را برای چک کردن اینکه آیا پروسهای روی پورت 5000 در حال اجراست، وارد کنید (پورت برنامه خود را جایگزین 5000 کنید):
sudo lsof -i:5000
- اگر خروجی این دستور خالی بود، یعنی برنامه شما اجرا نشده است.
قدم دوم: برنامه را دستی اجرا کنید.
- به پوشه پروژه خود بروید و آن را دستی اجرا کنید تا خطاها را ببینید:
cd /path/to/your/app
dotnet YourApp.dll
- به خروجی ترمینال دقت کنید. هر خطایی در
Startup.cs یا Program.cs اینجا نمایش داده میشود.
قدم سوم: لاگ خطای Nginx را بررسی کنید.
- این لاگ اطلاعات بسیار مفیدی در مورد دلیل عدم اتصال میدهد.
sudo tail -f /var/log/nginx/error.log
- در خروجی به دنبال عباراتی مانند
(111: Connection refused) بگردید که مستقیماً به عدم اجرای Kestrel اشاره دارد.
مشکل شماره ۲: پیکربندی نادرست proxy_pass
این دستور در فایل کانفیگ Nginx به آن میگوید که درخواستها را به کجا ارسال کند. یک اشتباه کوچک در این بخش کل ارتباط را مختل میکند.
نمونه کانفیگ اشتباه:
location / {
proxy_pass http://127.0.0.1:5001; # پورت برنامه 5000 است نه 5001
}نمونه کانفیگ صحیح:
فایل کانفیگ سایت شما معمولاً در /etc/nginx/sites-available/your-site قرار دارد.
server {
listen 80;
server_name your-domain.com; # دامنه خود را وارد کنید
location / {
# این بخش درخواست را به Kestrel ارسال میکند
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}نکته کلیدی: همیشه مطمئن شوید آدرس و پورت در proxy_pass دقیقاً همان آدرس و پورتی است که Kestrel روی آن اجرا شده است.
مشکل شماره ۳: عدم نصب NET Runtime.
شما ممکن است روی ماشین توسعه خود .NET SDK (کیت توسعه نرمافزار) را نصب کرده باشید که شامل همه چیز است. اما سرور پروداکشن فقط به ASP.NET Core Runtime (محیط اجرایی) نیاز دارد.
علامت مشکل:
وقتی برنامه را با دستور dotnet YourApp.dll اجرا میکنید، با خطایی مشابه زیر مواجه میشوید:
A fatal error occurred. The required library libhostfxr.so could not be found.
راهحل:
مطابق مستندات رسمی مایکروسافت، Runtime مناسب را روی سرور خود نصب کنید. برای مثال در اوبونتو ۲۲.۰۴ برای NET 8.:
# نصب ASP.NET Core Runtime 8.0
sudo apt-get update && \
sudo apt-get install -y aspnetcore-runtime-8.0
همیشه نسخه صحیح Runtime متناسب با Target Framework پروژه خود را نصب کنید.
مشکل شماره ۴: مسدود شدن توسط فایروال
فایروال لینوکس برای امنیت ضروری است، اما اگر به درستی پیکربندی نشود، مانع کار شما میشود. Nginx باید بتواند روی پورتهای 80 (HTTP) و 443 (HTTPS) به درخواستهای ورودی گوش دهد.
عیبیابی:
با استفاده از فایروال ufw (رایج در اوبونتو):
# وضعیت فایروال را بررسی کنید
sudo ufw status
# اگر فایروال فعال است، به Nginx اجازه دهید
sudo ufw allow 'Nginx Full'
# یا پورتها را دستی باز کنید
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# تغییرات را اعمال کنید
sudo ufw reload
مشکل شماره ۵: اجرای برنامه به صورت دستی (dotnet run)
بسیاری از افراد برای تست، برنامه را با dotnet YourApp.dll در یک ترمینال SSH اجرا میکنند.
مشکل: به محض اینکه شما پنجره ترمینال را ببندید یا اتصال SSH شما قطع شود، پروسه برنامه شما نیز از بین میرود (Kill میشود) و سایت شما از دسترس خارج شده و خطای 502 را برمیگرداند.
راهحل صحیح (پیشنمایش فصل بعد):
برنامه ASP.NET Core باید به عنوان یک سرویس (Service) در لینوکس اجرا شود. با این کار، سیستمعامل مسئولیت مدیریت آن را بر عهده میگیرد و تضمین میکند که:
- برنامه پس از ریبوت شدن سرور به طور خودکار اجرا شود.
- در صورت Crash کردن، به طور خودکار دوباره راهاندازی شود.
در فصل بعدی به طور کامل نحوه ساخت یک سرویس پایدار با استفاده از systemd را خواهیم آموخت.
جمعبندی فصل ۱:
در این فصل یاد گرفتیم که Nginx و Kestrel چگونه در کنار هم یک معماری قدرتمند را تشکیل میدهند. همچنین با شایعترین مشکلات اولیه مانند خطای 502، تنظیمات proxy_pass، نصب Runtime و پیکربندی فایروال آشنا شدیم. اکنون شما آمادهاید تا از این مرحله عبور کرده و در فصل بعد، برنامه خود را به یک سرویس پایدار و حرفهای تبدیل کنید.