ป้ายกำกับ: Dotnet

.NET: Server Service / Background Service.NET: Server Service / Background Service

การทำให้โปรแกรมที่พัฒนาด้วย .NET ( เช่น .NET 6, 7 หรือ .NET 8 ) ทำงานเป็น Server Service ( Background Service ) ช่วยให้ระบบสามารถเริ่มต้นทำงานได้เองโดยอัตโนมัติเมื่อเปิดเครื่อง ( Boot ) ทำงานอยู่เบื้องหลังโดยไม่ต้องมีผู้ใช้ Login ค้างไว้ และมีความอึด ถึก ทน หากแอปพลิเคชันพังก็สามารถตั้งค่าให้มัน Restart ตัวเองได้ บทความนี้จะพาคุณไปดูวิธีเปลี่ยนแอปพลิเคชัน .NET ให้เป็น Service ทั้งบน Windows ( Windows Service ) และ Linux ( systemd ) ด้วยโค้ดชุดเดียวกันครับ


การเตรียม Code ใน .NET ( Worker Service )

หัวใจสำคัญของการทำ Background Service ใน .NET ยุคใหม่คือการใช้ Worker Service Template หรือการเพิ่มชุดคำสั่งในโปรแกรมคอนโซลธรรมดาให้รองรับ Lifecycle ของระบบปฏิบัติการ


ขั้นตอนการเขียนโค้ด

หากเริ่มสร้างโปรเจกต์ใหม่ สามารถใช้คำสั่ง
dotnet new worker -n MyDotNetService
โครงสร้างหลักจะอยู่ที่ไฟล์ Program.cs และ Worker.cs ให้ทำการติดตั้ง NuGet Package ตาม OS ที่ต้องการใช้งาน

  • สำหรับ Windows: Microsoft.Extensions.Hosting.WindowsServices
  • สำหรับ Linux: Microsoft.Extensions.Hosting.Systemd

ปรับแต่ง Program.cs

แก้ไขไฟล์ Program.cs เพื่อบอกให้ .NET รู้ว่าต้องเปิดรับคำสั่งควบคุมการ Start/Stop จาก OS ด้วย

using MyDotNetService;

var builder = Host.CreateApplicationBuilder(args);

// รองรับการทำงานเป็น Windows Service
builder.Services.UseWindowsService(options =>
{
    options.ServiceName = "MyDotNetService";
});

// รองรับการทำงานเป็น Linux systemd Service
builder.Services.UseSystemd();

builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

( หมายความว่า โค้ดชุดนี้จะเอาไปรันบน Windows หรือ Linux ก็ได้ มันจะเลือกทำงานให้เหมาะสมกับ OS นั้น ๆ เองโดยอัตโนมัติ )


เขียน Logic ใน Worker.cs

ไฟล์นี้คือจุดที่งานของคุณจะทำงานอยู่เบื้องหลัง โดยสืบทอดมาจาก BackgroundService

namespace MyDotNetService;

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> _logger)
    {
        this._logger = _logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            
            // ใส่ Logic การทำงานของคุณตรงนี้ เช่น การเช็คคิวงาน, การดึงข้อมูลจาก Database
            
            await Task.Delay(5000, stoppingToken); // หน่วงเวลา 5 วินาที
        }
    }
}

เมื่อเขียนโค้ดเสร็จแล้ว ให้ทำการ Publish โปรแกรมออกมาเพื่อนำไปติดตั้ง
dotnet publish -c Release -r win-x64 --self-contained true -o ./publish-win
( เปลี่ยน -r เป็น linux-x64 หรือ linux-arm64 ตาม OS ปลายทาง )


การติดตั้งเป็น Windows Service

เมื่อได้ไฟล์จากการ Publish แล้ว ให้เปิด Command Prompt ( cmd ) หรือ PowerShell ด้วยสิทธิ์ Administrator


คำสั่งสร้าง Service

ใช้เครื่องมือ sc.exe ในการลงทะเบียน Service ( แนะนำให้ใส่ binPath ครอบด้วยเครื่องหมายคำพูด และมีเว้นวรรคหลังเครื่องหมาย = เสมอ )
sc.exe create "MyDotNetService" binPath= "C:\MyService\MyDotNetService.exe" start= auto
คำสั่งควบคุม

  • สั่งให้ทำงาน: sc.exe start MyDotNetService
  • สั่งให้หยุด: sc.exe stop MyDotNetService
  • ลบ Service ออกจากเครื่อง: sc.exe delete MyDotNetService

💡 ข้อดีบน Windows: คุณสามารถเปิดโปรแกรม services.msc เพื่อไปตั้งค่าในแท็บ Recovery ให้สิสเต็มสั่ง Restart the Service ตัวเองได้หากแอปพลิเคชันเกิด Crash


การติดตั้งเป็น Linux Service ( systemd )

สำหรับ Linux เราจะนิยมใช้ systemd ในการควบคุมการทำงานเบื้องหลัง
ขั้นตอนการติดตั้ง

  1. นำไฟล์ที่ Publish สำหรับ Linux ไปวางในโฟลเดอร์ที่ต้องการ เช่น /var/www/my-service/
  2. ให้สิทธิ์การรันไฟล์แอปพลิเคชัน
    chmod +x /var/www/my-service/MyDotNetService

สร้างไฟล์ Configuration ( .service )

สร้างไฟล์สำหรับบอก systemd ว่าต้องรันแอปพลิเคชันนี้อย่างไร
sudo nano /etc/systemd/system/mydotnet.service
ใส่เนื้อหา

[Unit]
Description=My .NET Server Service Application
After=network.target

[Service]
# กำหนดประเภทการรัน
Type=notify
# พาธของโฟลเดอร์และไฟล์รันโปรแกรม
WorkingDirectory=/var/www/my-service
ExecStart=/var/www/my-service/MyDotNetService
# ตั้งค่าให้ถ้าระบบพัง ให้ Restart ตัวเองภายใน 10 วินาที
Restart=always
RestartSec=10
# สิทธิ์ผู้ใช้งานที่ใช้รันโปรแกรม
User=www-data
# การจัดการ Log จาก Console
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

คำสั่งควบคุมบน Linux

เมื่อสร้างไฟล์เสร็จแล้ว ให้รันคำสั่งเหล่านี้เพื่อเปิดใช้งาน

# โหลดคอนฟิกของ systemd ใหม่
sudo systemctl daemon-reload

# ตั้งค่าให้เปิดใช้งานอัตโนมัติพร้อมเปิดเครื่อง (Boot)
sudo systemctl enable mydotnet.service

# สั่งให้ Service ทำงานทันที
sudo systemctl start mydotnet.service
  • เช็คสถานะการทำงาน
    sudo systemctl status mydotnet.service
  • ดู Log การทำงาน ( เสมือน Console )
    sudo journalctl -u mydotnet.service -f

สรุป

การเปลี่ยน .NET ให้เป็น Server Service ไม่ใช่เรื่องยากอีกต่อไปในปัจจุบัน ด้วยฟีเจอร์ Host Application Builder และ NuGet Package ที่สนับสนุนทั้งสองฝั่ง ทำให้คุณสามารถเขียน Code เพียงครั้งเดียว แต่สามารถ Deploy ลงบน Infrastructure แบบไหนก็ได้ ไม่ว่าจะเป็น Windows Server ดั้งเดิม หรือขยับขยายไปอยู่บน Linux Server เพื่อความประหยัดและยืดหยุ่นในอนาคต


อ่านเพิ่มเติม