1

我的目标是在 Windows 上创建一个在本地运行并使用 JSON 与本地程序通信的 Java 服务。服务应该是可靠和健壮的。

该服务运行一个 ServerSocket 并接收接收和响应 JSON 消息。以下是一个框架,其中适当的“命令”将添加到 SigningController 类中。该服务可能会保持小规模,并将包含约 10 个不同的命令。

问题

服务器看起来是否可靠(即没有潜在的挂断、异常等)?

我注意到,在大量使用之后(发送大量带有大字符串的“echo”命令),内存使用量增加到约 530mb,然后慢慢下降。我有资源或内存泄漏还是标准 JVM 行为?

也许题外话,但有没有办法改变任务管理器中显示的任务名称和图标?目前该进程显示为“Java(TM) Platform SE binary”。

该服务与nssm和 bat 文件一起安装

install.bat(以管理员身份)

@echo off
pushd %~dp0
nssm.exe stop JavaSigningService
nssm.exe remove JavaSigningService confirm
nssm.exe install JavaSigningService %~dp0start.bat
nssm.exe start JavaSigningService
popd
pause

开始.bat

java -Xmx512m -jar signingservice.jar

POM 文件和下面的类。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>Server.Main</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <finalName>signingservice</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <modelVersion>4.0.0</modelVersion>
    <groupId>...</groupId>
    <artifactId>signingservice</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
    </dependencies>

</project>

主要的

package Server;

import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static void main(String[] args) {
        int port = Integer.parseInt(args[0]);
        try (ServerSocket listener = new ServerSocket(port)) {
            System.out.println("Server is running...");
            ExecutorService pool = Executors.newFixedThreadPool(10);
            while (true) {
                try {
                    pool.execute(new Signer(listener.accept()));
                } catch (Exception e){
                    // Log
                }
            }
        } catch (Exception e) {
            // Log
        } finally {
            System.exit(0);
        }
    }
}

实用程序

package Server;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.PrintWriter;
import java.io.StringWriter;

public class Utils {
    private static JsonParser parser = new JsonParser();

    public static JsonObject getJsonFromString(String str) throws Exception{
        JsonObject jsonObject = parser.parse(str).getAsJsonObject();
        return jsonObject;
    }
    public static String getJsonProperty(JsonObject json, String property){
        String value = null;
        try {
            value = json.get(property).getAsString();
        } catch (Exception e) {}
        return value;
    }

    public static JsonObject errorMessageTemplate(Exception e){
        JsonObject result = new JsonObject();
        result.addProperty("result", "ERROR");
        result.addProperty("errormessage", e.getMessage());
        result.addProperty("stacktrace", stackTraceAsString(e));
        return result;
    }

    public static String stackTraceAsString(Exception e){
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        return sw.toString();
    }
}

签名控制器

package Server;

import com.google.gson.JsonObject;

public class SigningController {
    public static JsonObject handle(JsonObject received) throws Exception{
        String command = Utils.getJsonProperty(received, "command");
        if("echo".equals(command)){
            return simpleEcho(received);
        }
        return Utils.errorMessageTemplate(new Exception("Command not specified or unknown."));
    }

public static JsonObject simpleEcho(JsonObject received) throws Exception{
    String data = "" + Utils.getJsonProperty(received, "data");
    JsonObject result = new JsonObject();
    result.addProperty("result", "OK");
    result.addProperty("data", data);
    return result;
}
}

签名者

package Server;

import com.google.gson.JsonObject;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Signer implements Runnable{
    private Socket socket;
    private BufferedReader socketIn;
    private PrintWriter socketOut;

    Signer(Socket socket) throws IOException {
        this.socket = socket;
        this.socket.setSoTimeout(60*1000); // read timeout in milliseconds
        socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
        socketOut = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
    }

    @Override
    public void run() {
        System.out.println("Connected: " + socket);
        try {
            socketOut.println("hello");
            String line = socketIn.readLine();
            JsonObject json = Utils.getJsonFromString(line);
            JsonObject result = SigningController.handle(json);
            socketOut.println(result);
        } catch (Exception e){
            // Log
            System.out.println("Error: " + socket);
            e.printStackTrace();
            try {
                socketOut.println(Utils.errorMessageTemplate(e));
            } catch (Exception e1) {}
        } finally{
            // Cleanup
            try{
                socketIn.close();
            } catch (IOException e){
                e.printStackTrace();
            }
            try{
                socketOut.close();
            } catch (Exception e){
                e.printStackTrace();
            }
            try{
                socket.close();
                System.out.println("Closed: " + socket);
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
4

0 回答 0