From b8719d7f76ee908a91f7e4508d2d2d8704c4eea1 Mon Sep 17 00:00:00 2001 From: Redkale <8730487+redkale@users.noreply.github.com> Date: Thu, 18 Jun 2020 15:35:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=BB=E6=8E=89Service.stop=20=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20@Command=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/command.bat | 7 +++++ bin/command.sh | 23 +++++++++++++++ src/org/redkale/boot/Application.java | 26 +++++++++++++++-- src/org/redkale/boot/NodeServer.java | 42 +++++++++++++++++++++++++-- src/org/redkale/util/Command.java | 28 ++++++++++++++++++ 5 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 bin/command.bat create mode 100644 bin/command.sh create mode 100644 src/org/redkale/util/Command.java diff --git a/bin/command.bat b/bin/command.bat new file mode 100644 index 000000000..93ad7ab8b --- /dev/null +++ b/bin/command.bat @@ -0,0 +1,7 @@ +@ECHO OFF + +SET APP_HOME=%~dp0 + +IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0.. + +java -DCMD=%1 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application diff --git a/bin/command.sh b/bin/command.sh new file mode 100644 index 000000000..2e0005106 --- /dev/null +++ b/bin/command.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +export LC_ALL="zh_CN.UTF-8" + +APP_HOME=`dirname "$0"` + +cd "$APP_HOME"/.. + +APP_HOME=`pwd` + +if [ ! -f "$APP_HOME"/conf/application.xml ]; then + APP_HOME="$APP_HOME"/.. +fi + +lib="$APP_HOME"/lib +for jar in `ls $APP_HOME/lib/*.jar` +do + lib=$lib:$jar +done +export CLASSPATH=$CLASSPATH:$lib + +echo "$APP_HOME" +java -DCMD=$1 -DAPP_HOME="$APP_HOME" org.redkale.boot.Application diff --git a/src/org/redkale/boot/Application.java b/src/org/redkale/boot/Application.java index aa71337f6..3be10c4f6 100644 --- a/src/org/redkale/boot/Application.java +++ b/src/org/redkale/boot/Application.java @@ -764,7 +764,8 @@ public final class Application { buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); - if ("SHUTDOWN".equalsIgnoreCase(new String(bytes))) { + final String cmd = new String(bytes); + if ("SHUTDOWN".equalsIgnoreCase(cmd)) { try { long s = System.currentTimeMillis(); logger.info(application.getClass().getSimpleName() + " shutdowning"); @@ -784,7 +785,7 @@ public final class Application { buffer.flip(); channel.send(buffer, address); } - } else if ("APIDOC".equalsIgnoreCase(new String(bytes))) { + } else if ("APIDOC".equalsIgnoreCase(cmd)) { try { new ApiDocsService(application).run(); buffer.clear(); @@ -797,6 +798,16 @@ public final class Application { buffer.flip(); channel.send(buffer, address); } + } else { + long s = System.currentTimeMillis(); + logger.info(application.getClass().getSimpleName() + " command " + cmd); + application.command(cmd); + buffer.clear(); + buffer.put("COMMAND OK".getBytes()); + buffer.flip(); + channel.send(buffer, address); + long e = System.currentTimeMillis() - s; + logger.info(application.getClass().getSimpleName() + " command in " + e + " ms"); } } } catch (Exception e) { @@ -1095,6 +1106,17 @@ public final class Application { return null; } + public void command(String cmd) { + List localServers = new ArrayList<>(servers); //顺序sncps, others, watchs + localServers.stream().forEach((server) -> { + try { + server.command(cmd); + } catch (Exception t) { + logger.log(Level.WARNING, " command server(" + server.getSocketAddress() + ") error", t); + } + }); + } + public void shutdown() throws Exception { for (ApplicationListener listener : this.listeners) { try { diff --git a/src/org/redkale/boot/NodeServer.java b/src/org/redkale/boot/NodeServer.java index e68599ed9..f128e28bb 100644 --- a/src/org/redkale/boot/NodeServer.java +++ b/src/org/redkale/boot/NodeServer.java @@ -461,7 +461,7 @@ public abstract class NodeServer { final ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> { try { if (SncpClient.parseMethod(serviceImplClass).isEmpty() && serviceImplClass.getAnnotation(Priority.class) == null) { //class没有可用的方法且没有标记启动优先级的, 通常为BaseService - if (!serviceImplClass.getName().startsWith("org.redkale.") && !serviceImplClass.getSimpleName().contains("Base")){ + if (!serviceImplClass.getName().startsWith("org.redkale.") && !serviceImplClass.getSimpleName().contains("Base")) { logger.log(Level.FINE, serviceImplClass + " cannot load because not found less one public non-final method"); } return; @@ -535,8 +535,8 @@ public abstract class NodeServer { } if (isSNCP() && !sncpRemoteAgents.isEmpty()) { sncpRemoteAgents.values().forEach(agent -> { - // agent.putSncpResp((NodeSncpServer) this); - // agent.startSncpRespConsumer(); + // agent.putSncpResp((NodeSncpServer) this); + // agent.startSncpRespConsumer(); }); } //----------------- init ----------------- @@ -773,6 +773,42 @@ public abstract class NodeServer { server.shutdown(); } + public void command(String cmd) throws IOException { + final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; + final boolean finest = logger.isLoggable(Level.FINEST); + localServices.forEach(y -> { + Set methods = new HashSet<>(); + Class loop = y.getClass(); + //do { public方法不用递归 + for (Method m : loop.getMethods()) { + Command c = m.getAnnotation(Command.class); + if (c == null) continue; + if (Modifier.isStatic(m.getModifiers())) continue; + if (m.getReturnType() != void.class) continue; + if (m.getParameterCount() != 1) continue; + if (m.getParameterTypes()[0] != String.class) continue; + methods.add(m); + } + //} while ((loop = loop.getSuperclass()) != Object.class); + if (methods.isEmpty()) return; + long s = System.currentTimeMillis(); + Method one = null; + try { + for (Method method : methods) { + one = method; + method.invoke(y, cmd); + } + } catch (Exception ex) { + logger.log(Level.SEVERE, one + " run error, cmd = " + cmd, ex); + } + long e = System.currentTimeMillis() - s; + if (e > 10 && sb != null) { + sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" command (").append(cmd).append(") ").append(e).append("ms").append(LINE_SEPARATOR); + } + }); + if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); + } + public T getServer() { return (T) server; } diff --git a/src/org/redkale/util/Command.java b/src/org/redkale/util/Command.java new file mode 100644 index 000000000..80397eb27 --- /dev/null +++ b/src/org/redkale/util/Command.java @@ -0,0 +1,28 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.util; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 接收命令的标记, 只能标记在本地模式下Service里参数为String且返回类型为void的public方法上 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * + * @since 2.1.0 + */ +@Inherited +@Documented +@Target({METHOD}) +@Retention(RUNTIME) +public @interface Command { + +}