มาทำให้ Java Spring-boot Application ของเราทำงานเป็น Windows Service กันเถอะ!

Jittagornp
Lotus’s IT
Published in
5 min readJan 2, 2024

--

สวัสดีครับ ผมเดียร์จากทีม LSE (Lotus’s Store Engineering) นะครับ วันนี้จะมาขอแชร์วิธีการทำ Service รูปแบบนึงที่ทีม LSE เราใช้กันอยู่เป็นประจำ นั่นก็คือ การทำให้ Java Spring-boot Application ของเรา ทำงานเป็น Windows Service นั่นเอง

ก่อนที่จะเริ่มอ่านบทความ ผมขออนุมานว่าคนที่เข้ามาอ่านบทความนี้ เขียน Java Spring-boot กันเป็นอยู่แล้ว ขออนุญาตข้ามรายละเอียดเล็ก ๆ น้อย ๆ ของ Spring-boot ไปนะครับ

มาเริ่มกันเลยดีกว่า!

ทำไมต้องทำให้เป็น Windows Service?

เนื่องจาก Service ที่ทีม LSE เราพัฒนา มีทั้งแบบที่ต้อง Deploy บน Kubernetes และแบบที่ต้อง Deploy บน Windows Sever

แบบที่ต้อง Deploy บน Kubernetes แน่นอนว่าเรา Deploy กันเป็น Container อยู่แล้ว ส่วนแบบที่ต้อง Deploy บน Windows Server เนื่องจากเราไม่สามารถใช้ Container Technology ได้ ทีมเราเลยเลือกที่จะทำให้ Application ของเราทำงานเป็น Windows Service เนื่องจากว่ามันดูแลง่าย เวลา Service มีปัญหาอะไร เราสามารถที่จะเข้าไป Start/Stop/Restart Service ผ่าน Windows Task Manager ได้เลย หรือเขียน Auto Script ให้เข้าไป Control ผ่าน Service บน Kubernetes อีกทีได้

ใช้อะไรทำให้เป็น Windows Service?

เราใช้ Tool ที่ชื่อว่า WinSW (Windows Service Wrapper) ช่วยในการทำให้ Java Spring-boot Application สามารถทำงานเป็น Windows Service ได้

สามารถเข้าไปดูรายละเอียดของ Tool ได้ที่

หมายเหตุ

จริง ๆ แล้ว WinSW เป็น Tool ที่สามารถทำให้อะไรก็ตามที่สามารถ Execute ได้ กลายเป็น Windows Service ได้ทั้งหมดเลย ไม่ใช่เพียงแต่ Java Spring-boot เท่านั้นนะ

มาดูวิธีการทำกันดีกว่า

1. เตรียม Java Spring-boot Application ให้พร้อม

สมมติว่า เรามี Spring-boot Application อยู่แล้ว ดังนี้

การทำงานของ Application ในบทความนี้ จะเป็นการทำงานง่าย ๆ คือแค่ Request เข้ามาที่ Path / ระบบก็จะ Response status 200 กลับไป พร้อมข้อความตามภาพ

2. Download ไฟล์ WinSW เข้าไปใน Spring-boot Project

ถัดมา ให้เข้าไป Download ไฟล์ WinSW ที่หน้า https://github.com/winsw/winsw/releases เข้าไปไว้ใน Spring-boot Project ของเราแบบนี้

เอาไว้ที่ Path ไหนของ Project ก็ได้

จากภาพ ผมสร้าง Folder ที่ชื่อว่า windows-service เอาไว้เก็บไฟล์ WinSW

หมายเหตุ

ตอน Download ไฟล์ WinSW มาใช้ ให้เลือก Version ที่เข้ากันได้กับเครื่อง Windows Server และ Version ของ .Net Framework ที่เราจะเอา Application ของเราไป Deploy (Document ของ WinSW มีอธิบาย)

ในที่นี้ผมจะ Download WinSW version ล่าสุดมาใช้งาน

Download 2 ไฟล์นี้

  • WinSW-x64.exe คือไฟล์ Windows Service Wrapper ที่จะทำให้ Application ของเรากลายเป็น Windows Service
  • sample-minimal.xml ไฟล์นี้เป็น Simple Configurationให้เราใช้เป็นตัวอย่างในการ Config ซึ่งผม Download ลงมา แล้ว Rename ไฟล์ไปเป็น WinSW-x64.xml

3. แก้ Configuration ไฟล์ WinSW-x64.xml

คำอธิบาย

  • id — ID ของ Service ที่เราจะเอาไป Deploy บน Windows Server
  • name — ชื่อ Service ที่จะแสดงใน Windows Task Manager
  • description — คำอธิบายของ Service
  • executable — เมื่อ Service เริ่มทำงาน ให้ไปเรียกตัว Execute ใด ในที่นี้คือให้เรียก Java โดยใส่ Arguments ตาม tag arguments ด้านล่าง
  • arguments — ให้ทำการเรียก Spring-boot Application ที่เราทำเป็น Jar file ไว้

จริง ๆ แค่นี้ ก็สามารถที่จะเอาไป Deploy บน Windows Server ได้แล้วนะ แต่ผมจะขอทำเพิ่มเติมอีกนิดนึง คือ หลังจากที่ทำการ Build Spring-boot Application เสร็จแล้ว ให้ Maven ช่วย Pack สิ่งที่เราจะเอาไป Deploy บน Windows Server ไปเป็นไฟล์ .zip ให้หน่อย เพื่อที่จะได้ Download ไป Deploy หรือ Install บน Windows Server ได้ง่ายขึ้น

หากใครยังไม่คล่อง Maven สามารถเข้าไปอ่านเพิ่มเติมได้ที่ https://www.jittagornp.me/blog/what-is-apache-maven/

4. Pack Spring-boot Application ของเราไปเป็นไฟล์ .zip

ให้เราลง Maven Plugin ที่ชื่อว่า Assembly เพิ่มเติม https://maven.apache.org/plugins/maven-assembly-plugin/index.html

ใน pom.xml ในส่วนของ plugins ให้เราเพิ่มไปแบบนี้

5. เพิ่ม Configuration สำหรับ Maven Assembly Plugin (ไฟล์ distribution.xml)

ผมเอาไว้ที่ Path /assembly/distribution.xml ของ Project

distribution.xml

คำอธิบาย

  1. ให้ Maven Assembly Plugin ช่วย Pack ไฟล์ไปเป็น format zip
  2. โดยนำไฟล์ต่าง ๆ ตามที่เขียนไว้ใน tag files มา Pack ลง zip ดังนี้
  • เอาไฟล์ windows-service/WinSW-x64.exe มา Rename เป็น my-service.exe
  • เอาไฟล์ windows-service/WinSW-x64.xml มา Rename เป็น my-service.xml
  • เอาไฟล์ target/app.jar มา Rename เป็น my-service.jar

แล้วเอาทั้ง 3 ไฟล์ไปวางไว้ที่ Folder / ของ Zip

หมายเหตุ

ทั้ง 3 ไฟล์นี้ ให้ Rename เป็นชื่อไฟล์เดียวกัน (แต่คนละนามสกุล)

เมื่อ Build Application (mvn clean install) เสร็จแล้ว เราก็จะได้ไฟล์ .zip เพิ่มเติมเข้ามาใน Folder target และมีไฟล์ดังต่อไปนี้อยู่ใน .zip

  • my-service.exe
  • my-service.xml
  • my-service.jar

ทดลอง Build Application

เมื่อเราลอง Unzip ดู ก็จะเห็น 3 ไฟล์ตามที่เรา Config ไว้

6. ทดลอง Deploy/Install ในเครื่อง Windows

Prerequisites

  • ในเครื่อง Windows จะต้อง Install Java ไว้อยู่แล้ว (ในบทความนี้จะขอใช้เป็น Java — Open JDK 17)
  • ในเครื่องจะต้องมี .Net Framework Install ไว้อยู่แล้ว

สมมติว่าเราได้ Download ไฟล์ .zip มาไว้ที่เครื่อง Windows แล้ว ดังนี้

จากนั้นให้เรา Unzip

เราจะเห็นไฟล์ Service 3 ไฟล์ตามที่เรา Config ไว้ในหัวข้อที่ผ่านมา

ให้เรา run คำสั่ง

my-service.exe install

เพื่อทำการ Deploy/Install Service ของเราเข้าเครื่อง Windows

และ run คำสั่ง

my-service.exe start

เพื่อ start การทำงานของ service

หากลองเช็คที่ Windows Task Manager > Tab Services ก็จะพบว่ามี Service my-service ของเรา run ขึ้นมาแบบนี้

ลองเข้าผ่าน Web browser ของเครื่อง Windows ดู ก็จะสามารถเข้าใช้งาน Java Spring-boot Application ของเราได้เลย

หมายเหตุ

ถ้า Start service ไม่ขึ้น สามารถเข้าไปดู Log ได้ที่ไฟล์ my-service.wrapper.log ซึ่งไฟล์นี้จะถูกสร้างขึ้นมาอัตโนมัติ อยู่ข้าง ๆ ไฟล์ my-service.exe

แต่เราก็สามารถ Config log ให้เปลี่ยนไปอยู่ที่ Path อื่นได้นะ อ่านได้จาก Document ของ WinSW

ปกติที่เคยเจอ Error สำหรับ Java Application คือ WinSW หา java working directory ไม่เจอ หรือพูดง่าย ๆ คือ ไม่รู้จัก JAVA_HOME นั่นเอง

วิธีแก้ ให้เรา Fixed Path java เต็ม ๆ เข้าไปใน Config .xml เลยแบบนี้

แต่บาง Windows Server ก็ไม่เป็นปัญหานี้นะ

WinSW สามารถ run ได้หลายคำสั่ง ถ้าเราอยากรู้ว่ามีคำสั่งไหนให้เราใช้งานได้บ้าง ให้เรา run คำสั่ง help ดู ดังนี้

my-service.exe help

เราสามารถที่จะ install/uninstall/start/stop/restart หรือ check service status ผ่าน WinSW ได้

Source Code

หวังว่าบทความนี้จะเป็นประโยชน์ต่อเพื่อน ๆ Java Developer ทุกคนนะครับ

--

--

Jittagornp
Lotus’s IT

วิศกรซอฟต์แวร์ ที่หลงรักการเขียนซอฟต์แวร์ และมีความสุขกับการได้อยู่กับครอบครัว