使用NSSM在Windows 上运行 Java 服务(增加:自动重启 + JVM 参数优化)

40 阅读3分钟

「可直接上线用」的升级方案,在现有 NSSM + Spring Boot 的基础上增加:

✅ JVM 参数系统化优化
✅ 服务异常自动重启
✅ 内存溢出自动 dump
✅ GC 日志
✅ 避免频繁重启(防抖)
✅ 脚本 可重复执行(幂等)


一、升级后的整体能力图

JAR 崩溃
   ↓
NSSM 自动重启(延迟 5 秒)
   ↓
最多 3 次 / 10 分钟
   ↓
超过阈值 → 停止(防止雪崩)

同时 JVM:

  • 使用 G1GC
  • 控制内存
  • OOM 自动 dump
  • GC 日志滚动

二、JVM 参数(推荐生产配置)

🔥 JVM_OPTS(通用、稳定)

set JVM_OPTS=^
-Xms512m ^
-Xmx1024m ^
-XX:+UseG1GC ^
-XX:MaxGCPauseMillis=200 ^
-XX:+HeapDumpOnOutOfMemoryError ^
-XX:HeapDumpPath=%APP_HOME%\logs\heapdump ^
-Xlog:gc*,gc+heap=info:file=%APP_HOME%\logs\gc.log:time,uptime:filecount=5,filesize=10M ^
-Dfile.encoding=UTF-8 ^
-Duser.timezone=Asia/Shanghai

为什么这样配?

参数作用
Xms / Xmx固定堆,避免动态扩容抖动
G1GC服务端默认最优
MaxGCPauseMillis控制停顿
HeapDumpOOM 可追溯
GC 日志性能分析
文件滚动防止磁盘爆

三、自动重启策略(NSSM)

关键配置说明

配置含义
AppRestartDelay崩溃后延迟重启
AppThrottle多久内允许重启
AppExit退出码策略

四、🔥 终极升级版脚本(可直接用)

✅ service-install.bat(完整版)

@echo off
setlocal enabledelayedexpansion

REM ==========================
REM 基础配置
REM ==========================
set SERVICE_NAME=ParkOfficeService
set SERVICE_DISPLAY_NAME=Park Office System
set SERVICE_DESC=Park Office Spring Boot Service

set NSSM=D:\tools\nssm\nssm.exe
set JAVA_EXE=C:\Program Files\Java\jdk-17\bin\java.exe
set APP_HOME=D:\app\park-office
set JAR_NAME=app.jar

REM 创建日志目录
if not exist "%APP_HOME%\logs" mkdir "%APP_HOME%\logs"
if not exist "%APP_HOME%\logs\heapdump" mkdir "%APP_HOME%\logs\heapdump"

REM ==========================
REM JVM 参数(生产)
REM ==========================
set JVM_OPTS=^
-Xms512m ^
-Xmx1024m ^
-XX:+UseG1GC ^
-XX:MaxGCPauseMillis=200 ^
-XX:+HeapDumpOnOutOfMemoryError ^
-XX:HeapDumpPath=%APP_HOME%\logs\heapdump ^
-Xlog:gc*,gc+heap=info:file=%APP_HOME%\logs\gc.log:time,uptime:filecount=5,filesize=10M ^
-Dfile.encoding=UTF-8 ^
-Duser.timezone=Asia/Shanghai

REM ==========================
REM 判断服务是否存在
REM ==========================
sc query "%SERVICE_NAME%" >nul 2>&1
if %ERRORLEVEL% EQU 0 (
    echo [INFO] 服务已存在,跳过注册
    goto CONFIG_SERVICE
)

REM ==========================
REM 注册服务
REM ==========================
echo [INFO] 注册服务中...

"%NSSM%" install "%SERVICE_NAME%" "%JAVA_EXE%" ^
    %JVM_OPTS% -jar "%APP_HOME%%JAR_NAME%"

"%NSSM%" set "%SERVICE_NAME%" AppDirectory "%APP_HOME%"
"%NSSM%" set "%SERVICE_NAME%" DisplayName "%SERVICE_DISPLAY_NAME%"
"%NSSM%" set "%SERVICE_NAME%" Description "%SERVICE_DESC%"

REM ==========================
REM 服务配置(无论是否存在都执行)
REM ==========================
:CONFIG_SERVICE

REM 日志
"%NSSM%" set "%SERVICE_NAME%" AppStdout "%APP_HOME%\logs\stdout.log"
"%NSSM%" set "%SERVICE_NAME%" AppStderr "%APP_HOME%\logs\stderr.log"
"%NSSM%" set "%SERVICE_NAME%" AppRotateFiles 1
"%NSSM%" set "%SERVICE_NAME%" AppRotateOnline 1
"%NSSM%" set "%SERVICE_NAME%" AppRotateBytes 10485760

REM ==========================
REM 自动重启策略(重点)
REM ==========================

REM 5 秒后重启
"%NSSM%" set "%SERVICE_NAME%" AppRestartDelay 5000

REM 10 分钟内最多 3 次重启
"%NSSM%" set "%SERVICE_NAME%" AppThrottle 600000

REM 非 0 退出码才重启
"%NSSM%" set "%SERVICE_NAME%" AppExit Default Restart

REM 开机自启
"%NSSM%" set "%SERVICE_NAME%" Start SERVICE_AUTO_START

echo [SUCCESS] 服务配置完成

REM ==========================
REM 启动服务
REM ==========================
net start "%SERVICE_NAME%"

echo [SUCCESS] 服务启动完成
pause

五、运行效果你会看到什么?

✔ 正常运行

Java 17
Spring Boot started

✔ OOM 时

java.lang.OutOfMemoryError
Heap dump created at:
D:\app\park-office\logs\heapdump\java_pid1234.hprof

✔ 崩溃后

NSSM: restarting service in 5000ms

六、常见调优建议(给你几个可选升级)

1️⃣ 机器 8G 内存以上

-Xms1g -Xmx2g

2️⃣ 高并发接口

-XX:MaxGCPauseMillis=100

3️⃣ Spring Boot 优化(建议加)

-Dspring.profiles.active=prod
-Dspring.main.lazy-initialization=true