มาทำให้ Java Spring-boot Application ของเราทำงานเป็น Windows Service กันเถอะ!
สวัสดีครับ ผมเดียร์จากทีม 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
คำอธิบาย
- ให้ Maven Assembly Plugin ช่วย Pack ไฟล์ไปเป็น format zip
- โดยนำไฟล์ต่าง ๆ ตามที่เขียนไว้ใน 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 ทุกคนนะครับ