用Java Service Wrapper将java程序制作成系统服务进程

用途

在做完一个项目程序后,有时会有两种需求想法。

1.在每次机器重启后自动运行程序。

2.在程序运行过程中如果发生了死锁、内存溢出或程序崩溃等问题时程序能自动重启。

当然。要实现这两种效果的方案有很多。可以在系统引导文件中加入开机运行程序引导,也可以写一个系统监听程序等等。

现在有一个更简单的解决方案。有一个java程序叫Java Service Wrapper。这是用来在windows或unix/linux系统中将java程序包装成系统服务并执行守护进程。

Java Service Wrapper有三个版本。professional/standard/community 前两个版本要收费功能也更多。对我们来说,社区版的已经够用了,(对于死锁重启需要收费版的)。

 

分析

从软件的名子上就能看出来。这个软件是用来包装的。我们的程序完成以后会有一个main入口。wrapper就是将这个main方法进行包装再提供自己的一个main入口。这样,我们在运行时都是运行的wrapper的程序。它会建立各种监控和服务,在建立完成后再加载运行被包装的方法。等监控到运行的程序出问题了就会进行相应的处理。

 

所需文件(以windows版本为例)

1.从官网http://wrapper.tanukisoftware.com上下载wrapper的软件。

2.我们只需要几个核心的文件

 

  • wrapper.jar 核心文件,位于lib文件夹中
  • wrapper.exe 因为是在windows系统中运行所以需要。位于bin文件夹中
  • wrapper.dll   因为是在windows系统中运行所以需要。 位于lib文件夹中
  • wrapper.conf 核心配置文件,位于src/conf文件夹中,将后缀名conf.in改成conf
  • App.bat (可选)运行你的程序,位于src/bin文件夹中, 将后缀名conf.in改成conf
  • InstallApp-NT.bat  (可选)将你的程序配置为系统服务,位于src/bin文件夹中, 将后缀名conf.in改成conf
  • UninstallApp-NT.bat   (可选)将你的程序从系统服务中删除,位于src/bin文件夹中, 将后缀名conf.in改成conf
  • StartApp-NT.bat   (可选)启动程序的系统服务,位于src/bin文件夹中, 将后缀名conf.in改成conf
  • StopApp-NT.bat   (可选)停止程序的系统服务,位于src/bin文件夹中, 将后缀名conf.in改成conf
  • XXX.jar/XXX.class 你的程序

实现方式

针对不同程序有不同的实现方式。

1.如果你的程序是不间断运行的。则只需要设置配置文件即可。

2.如果你的程序只是在系统启动时运行一次,或不需要连续运行的,则要加入入口包装类。不然,虽然你的程序已经执行成功且退出了(如:在系统启动时检查下环境再给你的提示信息就结束)。但wrapper会认为你的程序不应该结束,会不停的重启你的服务。这时你要加入包装类就没有这个问题了。

 

示例(我的原程序名为Out.java)

一、通用配置

1.在桌面上建一文件夹,并将所需文件都放入到该文件夹中,不分子文件夹(主要是展示如何配置自定义文件位置)
2.更改所有的bat文件内容。主要是修改相应的config文件位置。
在每个bat文件中找到 set _WRAPPER_CONF_DEFAULT 这个KEY,改为conf文件所在位置,现在是在同一文件夹中。所以配置为 set _WRAPPER_CONF_DEFAULT=./wrapper.conf
3.配置warpper.conf文件。主要有以下几点配置。要监控的入口类、JAVA_HOME地址、classpath、JVM设置、入口参数、记录配置、触发器监控事件处理、系统服务名等等,一般都可以使用默认配置。主要要修改的注意以下几项
wrapper.java.mainclass=Out 入口类,这里我的程序就是Out
wrapper.java.classpath.1=./wrapper.jar 运行需要的jar包,这里主要是wrapper.jar核心包,还有当前文件夹下的class文件。如果有别的还可以再加
wrapper.java.classpath.2=.
wrapper.filter.trigger.1000=Exception in thread "*" java.lang.OutOfMemoryError 这里是监控控制台输出的,如果字符串相同,则进行相应的处理,这里是监控是否有内存溢出,如果有则重启
wrapper.filter.action.1000=RESTART

二、原程序不间断运行

原程序内容

 

public class Out{
	public static void main(String[] args) throws Exception{
    System.out.println("\u7a0b\u5e8f\u5f00\u59cb\u8fd0\u884c...");
	}
}

 

原程序中只是打印一句话就结束。而我们要的效果是不间断运行,所以wrapper会不断的重启原程序,而会不断的打印语句。

 

只要改配置文件中的 wrapper.java.mainclass=Out 即可

在运行App.bat之后,你会发现程序会不断的被重启。

 

三、在内存溢出后重启

原程序内容

 

public class Out{
	public static void main(String[] args) throws Exception{
		System.out.println("\u7a0b\u5e8f\u5f00\u59cb\u8fd0\u884c...");
		String a="a";
		try{
				Thread.sleep(2000);
		}catch(Exception e){}
		System.out.println("\u7a0b\u5e8f\u5f00\u59cb\u5185\u5b58\u6ea2\u51fa...");
		
		for(int i=0;i<999999999;i++){
			a+=a;		
		}
		
		System.out.println("end");
	}
}

 

 原程序中应该能打印3句话,但在打印第二句后就会内存被溢出,最后的end不会被打印。但wrapper发现内存溢出后,会自动重启程序,再次不停的打印前两句和重启。

 

更改配置文件中内容

wrapper.java.mainclass=Out

 

wrapper.filter.trigger.1000=Exception in thread "*" java.lang.OutOfMemoryError

wrapper.filter.action.1000=RESTART

 

运行App.bat后会不停的打印前两句话并不停的重启。

四、程序只运行一次,但如果在运行中出现问题程序将重启

原程序内容
public class Out{
	public static void main(String[] args) throws Exception{
		System.out.println("\u7a0b\u5e8f\u5f00\u59cb\u8fd0\u884c...");
		String a="a";
		try{
				Thread.sleep(2000);
		}catch(Exception e){}

		if(args.length>0){
		System.out.println("\u7a0b\u5e8f\u5f00\u59cb\u5185\u5b58\u6ea2\u51fa...");
		for(int i=0;i<999999999;i++){
			a+=a;		
		}
		}
		
		System.out.println("end");
	}
}
效果。如果我们不传参数, 程序将会打印开始和结束语句,表示程序正常运行和结束,结束后程序不会重启。如果传了任意参数,则表示程序在运行中会出现内存溢出的错误,则程序会被重启。

这里我们要对入口类进行包装。

对于入口的包装有多种方式。这里不多讲,只讲一个对我们原程序无需代码更改的方式。
方法是,我们自己重新写一个入口类来包装原程序入口类。
包装类起名为Main.java 内容为
import org.tanukisoftware.wrapper.WrapperListener;
import org.tanukisoftware.wrapper.WrapperManager;

public class Main implements WrapperListener{
	public static void main(String[] args) throws Exception{
		Out.main(args);
		WrapperManager.start(new Main(),args);
	}

	public Integer start(String[] args) {
       System.out.println("start()");
       return null;
    }

    public int stop(int exitCode) {
       System.out.println("stop(" + exitCode + ")");
       return exitCode;
    }

    public void controlEvent(int event) {
       System.out.println("controlEvent(" + event + ")");
    }
}
 这里主要就是实现了wrapper的监听接口。在main方法里启动我们程序的真正入口。

更改配置文件内容
wrapper.java.mainclass=Main
wrapper.app.parameter.1= 注意这里是对程序进行传参用的,为空则是不传,写入字符就是要传的参数

wrapper.filter.trigger.1000=Exception in thread "*" java.lang.OutOfMemoryError

wrapper.filter.action.1000=RESTART

 

 

运行App.bat后会打印出相应语句并正常结束。、

如果把上面的配置改一下
wrapper.app.parameter.1=1
运行App.bat后会打印开始语句并发现有内存溢出,将重启程序。

 

备用

好了,Java Service Wrapper的基本使用就是这么简单。

把第四个示例的内存溢出打个包在这里备份下。以便自己以后使用。

你可能感兴趣的:(service)