Transport 改版
This commit is contained in:
@@ -27,15 +27,24 @@
|
|||||||
|
|
||||||
<!-- 所有服务所需的资源 -->
|
<!-- 所有服务所需的资源 -->
|
||||||
<resources>
|
<resources>
|
||||||
<!--
|
<!--
|
||||||
|
transport节点只能有一个,用于配置所有Transport的池参数,没配置该节点将自动创建一个。
|
||||||
|
threads: 线程总数, 默认: <group>节点数*CPU核数*8
|
||||||
|
bufferCapacity: ByteBuffer的初始化大小, 默认: 8K;
|
||||||
|
bufferPoolSize: ByteBuffer池的大小,默认: <group>节点数*CPU核数*8
|
||||||
|
-->
|
||||||
|
<transport capacity="8192" bufferPoolSize="32" threads="32"/>
|
||||||
|
<!--
|
||||||
一个组包含多个NODE, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
一个组包含多个NODE, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
||||||
name: 服务组ID,长度不能超过11个字节. 默认为空字符串。
|
一个group节点对应一个 Transport 对象。
|
||||||
|
name: 服务组ID,长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。
|
||||||
protocol:值只能是UDP TCP, 默认TCP
|
protocol:值只能是UDP TCP, 默认TCP
|
||||||
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息, 就必须有group节点信息。
|
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息, 就必须有group节点信息。
|
||||||
-->
|
-->
|
||||||
<group name="" protocol="TCP">
|
<group name="" protocol="TCP">
|
||||||
<!--
|
<!--
|
||||||
需要将本地node的addr与port列在此处。
|
需要将本地node的addr与port列在此处。
|
||||||
|
同一个<node>节点值只能存在一个<group>节点内,即同一个addr+port只能属于一个group。
|
||||||
addr: required IP地址
|
addr: required IP地址
|
||||||
port: required 端口
|
port: required 端口
|
||||||
clients: 连接池数, 默认: CPU核数*4
|
clients: 连接池数, 默认: CPU核数*4
|
||||||
@@ -73,7 +82,7 @@
|
|||||||
backlog: 默认10K
|
backlog: 默认10K
|
||||||
threads: 线程总数, 默认: CPU核数*16
|
threads: 线程总数, 默认: CPU核数*16
|
||||||
maxbody: request.body最大值, 默认: 64K
|
maxbody: request.body最大值, 默认: 64K
|
||||||
capacity: ByteBuffer的初始化大小, 默认: 8K; 如果是HTTP协议则默认: 16K + 8B (兼容HTTP 2.0)
|
bufferCapacity: ByteBuffer的初始化大小, 默认: 8K; 如果是HTTP协议则默认: 16K + 8B (兼容HTTP 2.0)
|
||||||
bufferPoolSize: ByteBuffer池的大小,默认: CPU核数*512
|
bufferPoolSize: ByteBuffer池的大小,默认: CPU核数*512
|
||||||
responsePoolSize: Response池的大小,默认: CPU核数*256
|
responsePoolSize: Response池的大小,默认: CPU核数*256
|
||||||
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
||||||
@@ -98,7 +107,7 @@
|
|||||||
<!-- 显著加载指定的Service的接口类 -->
|
<!-- 显著加载指定的Service的接口类 -->
|
||||||
<service value="com.xxx.XXX1Service"/>
|
<service value="com.xxx.XXX1Service"/>
|
||||||
<!--
|
<!--
|
||||||
name: 显式指定name,覆盖默认的空字符串值。
|
name: 显式指定name,覆盖默认的空字符串值。 注意: name不能包含$符号。
|
||||||
groups: 显式指定groups,覆盖<services>节点的groups默认值。
|
groups: 显式指定groups,覆盖<services>节点的groups默认值。
|
||||||
-->
|
-->
|
||||||
<service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/>
|
<service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/>
|
||||||
@@ -113,7 +122,7 @@
|
|||||||
当Server为HTTP协议时, request节点才有效。
|
当Server为HTTP协议时, request节点才有效。
|
||||||
remoteaddr 节点: 替换请求方节点的IP地址, 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。
|
remoteaddr 节点: 替换请求方节点的IP地址, 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。
|
||||||
且value值只能是以request.headers.开头,表示从request.headers中获取对应的header值。
|
且value值只能是以request.headers.开头,表示从request.headers中获取对应的header值。
|
||||||
例如下面例子获取request.getRemoteAddr()值,如果header存在X-RemoteAddress值则返回X-RemoteAddress值,不存在返回request.getRemoteAddress()。
|
例如下面例子获取request.getRemoteAddr()值,如果header存在X-RemoteAddress值则返回X-RemoteAddress值,不存在返回getRemoteAddress()。
|
||||||
-->
|
-->
|
||||||
<request>
|
<request>
|
||||||
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
||||||
|
|||||||
@@ -63,19 +63,18 @@ public final class Application {
|
|||||||
public static final String RESNAME_APP_NODES = "APP_NODES";
|
public static final String RESNAME_APP_NODES = "APP_NODES";
|
||||||
|
|
||||||
//当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
|
//当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
|
||||||
public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR"; // SERVER_ADDR
|
public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR";
|
||||||
|
|
||||||
//当前SNCP Server所属的组 类型: String
|
//当前SNCP Server所属的组 类型: String
|
||||||
public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP";
|
public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP";
|
||||||
|
|
||||||
//当前Service所属的组 类型: Set<String>、String[]
|
|
||||||
public static final String RESNAME_SNCP_GROUPS = Sncp.RESNAME_SNCP_GROUPS; // SNCP_GROUPS
|
|
||||||
|
|
||||||
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
|
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
|
||||||
|
|
||||||
final Map<String, Set<InetSocketAddress>> globalGroups = new HashMap<>();
|
final Map<String, Set<InetSocketAddress>> globalGroups = new HashMap<>();
|
||||||
|
|
||||||
final List<Transport> transports = new ArrayList<>();
|
final Map<String, String> globalGroupProtocols = new HashMap<>();
|
||||||
|
|
||||||
|
final Map<String, Transport> transports = new HashMap<>();
|
||||||
|
|
||||||
final InetAddress localAddress;
|
final InetAddress localAddress;
|
||||||
|
|
||||||
@@ -87,12 +86,18 @@ public final class Application {
|
|||||||
|
|
||||||
CountDownLatch servicecdl; //会出现两次赋值
|
CountDownLatch servicecdl; //会出现两次赋值
|
||||||
|
|
||||||
|
final ObjectPool<ByteBuffer> transportBufferPool;
|
||||||
|
|
||||||
|
final ExecutorService transportExecutor;
|
||||||
|
|
||||||
|
final AsynchronousChannelGroup transportChannelGroup;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------
|
||||||
private final ResourceFactory factory = ResourceFactory.root();
|
private final ResourceFactory factory = ResourceFactory.root();
|
||||||
|
|
||||||
private final WatchFactory watch = WatchFactory.root();
|
private final WatchFactory watch = WatchFactory.root();
|
||||||
|
|
||||||
private File home;
|
private final File home;
|
||||||
|
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
@@ -185,6 +190,47 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||||
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
|
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
|
||||||
|
//------------------配置 <transport> 节点 ------------------
|
||||||
|
ObjectPool<ByteBuffer> transportPool = null;
|
||||||
|
ExecutorService transportExec = null;
|
||||||
|
AsynchronousChannelGroup transportGroup = null;
|
||||||
|
final AnyValue resources = config.getAnyValue("resources");
|
||||||
|
if (resources != null) {
|
||||||
|
AnyValue transportConf = resources.getAnyValue("transport");
|
||||||
|
int groupsize = resources.getAnyValues("group").length;
|
||||||
|
if (groupsize > 0 && transportConf == null) transportConf = new DefaultAnyValue();
|
||||||
|
if (transportConf != null) {
|
||||||
|
//--------------transportBufferPool-----------
|
||||||
|
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + ".Buffer.creatCounter");
|
||||||
|
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + ".Buffer.cycleCounter");
|
||||||
|
final int bufferCapacity = transportConf.getIntValue("bufferCapacity", 8 * 1024);
|
||||||
|
final int bufferPoolSize = transportConf.getIntValue("bufferPoolSize", groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
||||||
|
final int threads = transportConf.getIntValue("threads", groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
||||||
|
transportPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, bufferPoolSize,
|
||||||
|
(Object... params) -> ByteBuffer.allocateDirect(bufferCapacity), null, (e) -> {
|
||||||
|
if (e == null || e.isReadOnly() || e.capacity() != bufferCapacity) return false;
|
||||||
|
e.clear();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
//-----------transportChannelGroup--------------
|
||||||
|
try {
|
||||||
|
final AtomicInteger counter = new AtomicInteger();
|
||||||
|
transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.setName("Transport-Thread-" + counter.incrementAndGet());
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
transportGroup = AsynchronousChannelGroup.withCachedThreadPool(transportExec, 1);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
logger.log(Level.INFO, Transport.class.getSimpleName() + " configure bufferCapacity = " + bufferCapacity + "; bufferPoolSize = " + bufferPoolSize + "; threads = " + threads + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.transportBufferPool = transportPool;
|
||||||
|
this.transportExecutor = transportExec;
|
||||||
|
this.transportChannelGroup = transportGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceFactory getResourceFactory() {
|
public ResourceFactory getResourceFactory() {
|
||||||
@@ -279,13 +325,14 @@ public final class Application {
|
|||||||
|
|
||||||
for (AnyValue conf : resources.getAnyValues("group")) {
|
for (AnyValue conf : resources.getAnyValues("group")) {
|
||||||
final String group = conf.getValue("name", "");
|
final String group = conf.getValue("name", "");
|
||||||
String protocol = conf.getValue("protocol", Transport.DEFAULT_PROTOCOL).toUpperCase();
|
final String protocol = conf.getValue("protocol", Transport.DEFAULT_PROTOCOL).toUpperCase();
|
||||||
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
|
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
|
||||||
throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
|
throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
|
||||||
}
|
}
|
||||||
Set<InetSocketAddress> addrs = globalGroups.get(group);
|
Set<InetSocketAddress> addrs = globalGroups.get(group);
|
||||||
if (addrs == null) {
|
if (addrs == null) {
|
||||||
addrs = new LinkedHashSet<>();
|
addrs = new LinkedHashSet<>();
|
||||||
|
globalGroupProtocols.put(group, protocol);
|
||||||
globalGroups.put(group, addrs);
|
globalGroups.put(group, addrs);
|
||||||
}
|
}
|
||||||
for (AnyValue node : conf.getAnyValues("node")) {
|
for (AnyValue node : conf.getAnyValues("node")) {
|
||||||
@@ -479,8 +526,8 @@ public final class Application {
|
|||||||
public static <T extends Service> T singleton(Class<T> serviceClass, boolean remote) throws Exception {
|
public static <T extends Service> T singleton(Class<T> serviceClass, boolean remote) throws Exception {
|
||||||
final Application application = Application.create();
|
final Application application = Application.create();
|
||||||
Consumer<Runnable> executor = (x) -> Executors.newFixedThreadPool(8).submit(x);
|
Consumer<Runnable> executor = (x) -> Executors.newFixedThreadPool(8).submit(x);
|
||||||
T service = remote ? Sncp.createRemoteService("", executor, serviceClass, null, new LinkedHashSet<>(), null)
|
T service = remote ? Sncp.createRemoteService("", executor, serviceClass, null, null)
|
||||||
: Sncp.createLocalService("", executor, serviceClass, null, new LinkedHashSet<>(), null, null);
|
: Sncp.createLocalService("", executor, serviceClass, null, null, null);
|
||||||
application.init();
|
application.init();
|
||||||
application.factory.register(service);
|
application.factory.register(service);
|
||||||
application.servicecdl = new CountDownLatch(1);
|
application.servicecdl = new CountDownLatch(1);
|
||||||
@@ -515,6 +562,11 @@ public final class Application {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String findGroupProtocol(String group) {
|
||||||
|
if (group == null) return null;
|
||||||
|
return globalGroupProtocols.get(group);
|
||||||
|
}
|
||||||
|
|
||||||
Set<InetSocketAddress> findGlobalGroup(String group) {
|
Set<InetSocketAddress> findGlobalGroup(String group) {
|
||||||
if (group == null) return null;
|
if (group == null) return null;
|
||||||
Set<InetSocketAddress> set = globalGroups.get(group);
|
Set<InetSocketAddress> set = globalGroups.get(group);
|
||||||
@@ -546,6 +598,13 @@ public final class Application {
|
|||||||
logger.log(Level.FINER, "close CacheSource erroneous", e);
|
logger.log(Level.FINER, "close CacheSource erroneous", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.transportChannelGroup != null) {
|
||||||
|
try {
|
||||||
|
this.transportChannelGroup.shutdownNow();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.FINER, "close transportChannelGroup erroneous", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnyValue load(final InputStream in0) {
|
private static AnyValue load(final InputStream in0) {
|
||||||
|
|||||||
@@ -269,6 +269,10 @@ public final class ClassFilter<T> {
|
|||||||
public FilterEntry(Class<T> type, final boolean autoload, AnyValue property) {
|
public FilterEntry(Class<T> type, final boolean autoload, AnyValue property) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
String str = property == null ? null : property.getValue("groups");
|
String str = property == null ? null : property.getValue("groups");
|
||||||
|
if (str != null) {
|
||||||
|
str = str.trim();
|
||||||
|
if (str.endsWith(";")) str = str.substring(0, str.length() - 1);
|
||||||
|
}
|
||||||
if (str != null) groups.addAll(Arrays.asList(str.split(";")));
|
if (str != null) groups.addAll(Arrays.asList(str.split(";")));
|
||||||
this.property = property;
|
this.property = property;
|
||||||
this.autoload = autoload;
|
this.autoload = autoload;
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ import org.redkale.util.*;
|
|||||||
/**
|
/**
|
||||||
* HTTP Server节点的配置Server
|
* HTTP Server节点的配置Server
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@NodeProtocol({"HTTP"})
|
@NodeProtocol({"HTTP"})
|
||||||
@@ -34,7 +36,7 @@ public final class NodeHttpServer extends NodeServer {
|
|||||||
private final HttpServer httpServer;
|
private final HttpServer httpServer;
|
||||||
|
|
||||||
public NodeHttpServer(Application application, AnyValue serconf) {
|
public NodeHttpServer(Application application, AnyValue serconf) {
|
||||||
super(application, application.getResourceFactory().createChild(), createServer(application, serconf));
|
super(application, createServer(application, serconf));
|
||||||
this.httpServer = (HttpServer) server;
|
this.httpServer = (HttpServer) server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +56,7 @@ public final class NodeHttpServer extends NodeServer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
||||||
if (httpServer != null) loadHttpServlet(this.nodeConf.getAnyValue("servlets"), servletFilter);
|
if (httpServer != null) loadHttpServlet(this.serverConf.getAnyValue("servlets"), servletFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -66,28 +68,17 @@ public final class NodeHttpServer extends NodeServer {
|
|||||||
private void initWebSocketService() {
|
private void initWebSocketService() {
|
||||||
final NodeServer self = this;
|
final NodeServer self = this;
|
||||||
final ResourceFactory regFactory = application.getResourceFactory();
|
final ResourceFactory regFactory = application.getResourceFactory();
|
||||||
factory.add(WebSocketNode.class, (ResourceFactory rf, final Object src, final String resourceName, Field field, Object attachment) -> {
|
factory.add(WebSocketNode.class, (ResourceFactory rf, final Object src, final String resourceName, Field field, Object attachment) -> { //主要用于单点的服务
|
||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
if (!(src instanceof WebSocketServlet)) return;
|
if (!(src instanceof WebSocketServlet)) return;
|
||||||
synchronized (regFactory) {
|
synchronized (regFactory) {
|
||||||
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
||||||
if (nodeService == null) {
|
if (nodeService == null) {
|
||||||
nodeService = Sncp.createLocalService(resourceName, getExecutor(), (Class<? extends Service>) WebSocketNodeService.class,
|
nodeService = Sncp.createLocalService(resourceName, getExecutor(), WebSocketNodeService.class, (InetSocketAddress) null, (Transport) null, (Collection<Transport>) null);
|
||||||
getSncpAddress(), sncpDefaultGroups, sncpSameGroupTransports, sncpDiffGroupTransports);
|
|
||||||
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
||||||
factory.inject(nodeService, self);
|
factory.inject(nodeService, self);
|
||||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
||||||
if (getSncpAddress() != null) {
|
|
||||||
NodeSncpServer sncpServer = null;
|
|
||||||
for (NodeServer node : application.servers) {
|
|
||||||
if (node.isSNCP() && getSncpAddress().equals(node.getSncpAddress())) {
|
|
||||||
sncpServer = (NodeSncpServer) node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ServiceWrapper wrapper = new ServiceWrapper(WebSocketNodeService.class, nodeService, resourceName, getSncpGroup(), sncpDefaultGroups, null);
|
|
||||||
sncpServer.getSncpServer().addService(wrapper);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
field.set(src, nodeService);
|
field.set(src, nodeService);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.logging.*;
|
|||||||
import javax.annotation.*;
|
import javax.annotation.*;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.source.*;
|
import org.redkale.source.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
@@ -57,27 +56,19 @@ public abstract class NodeServer {
|
|||||||
|
|
||||||
private String sncpGroup = null; //当前Server的SNCP协议的组
|
private String sncpGroup = null; //当前Server的SNCP协议的组
|
||||||
|
|
||||||
private String nodeProtocol = Transport.DEFAULT_PROTOCOL;
|
|
||||||
|
|
||||||
private InetSocketAddress sncpAddress; //HttpServer中的sncpAddress 为所属group对应的SncpServer, 为null表示只是单节点,没有分布式结构
|
private InetSocketAddress sncpAddress; //HttpServer中的sncpAddress 为所属group对应的SncpServer, 为null表示只是单节点,没有分布式结构
|
||||||
|
|
||||||
protected Consumer<ServiceWrapper> consumer;
|
protected Consumer<ServiceWrapper> consumer;
|
||||||
|
|
||||||
protected AnyValue nodeConf;
|
protected AnyValue serverConf;
|
||||||
|
|
||||||
protected final HashSet<String> sncpDefaultGroups = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
protected final List<Transport> sncpSameGroupTransports = new ArrayList<>();
|
|
||||||
|
|
||||||
protected final List<Transport> sncpDiffGroupTransports = new ArrayList<>();
|
|
||||||
|
|
||||||
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
||||||
|
|
||||||
protected final Set<ServiceWrapper> remoteServiceWrappers = new LinkedHashSet<>();
|
protected final Set<ServiceWrapper> remoteServiceWrappers = new LinkedHashSet<>();
|
||||||
|
|
||||||
public NodeServer(Application application, ResourceFactory factory, Server server) {
|
public NodeServer(Application application, Server server) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.factory = factory;
|
this.factory = application.getResourceFactory().createChild();
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||||
this.fine = logger.isLoggable(Level.FINE);
|
this.fine = logger.isLoggable(Level.FINE);
|
||||||
@@ -115,16 +106,15 @@ public abstract class NodeServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init(AnyValue config) throws Exception {
|
public void init(AnyValue config) throws Exception {
|
||||||
this.nodeConf = config == null ? AnyValue.create() : config;
|
this.serverConf = config == null ? AnyValue.create() : config;
|
||||||
if (isSNCP()) { // SNCP协议
|
if (isSNCP()) { // SNCP协议
|
||||||
String host = this.nodeConf.getValue("host", "0.0.0.0").replace("0.0.0.0", "");
|
String host = this.serverConf.getValue("host", "0.0.0.0").replace("0.0.0.0", "");
|
||||||
this.sncpAddress = new InetSocketAddress(host.isEmpty() ? application.localAddress.getHostAddress() : host, this.nodeConf.getIntValue("port"));
|
this.sncpAddress = new InetSocketAddress(host.isEmpty() ? application.localAddress.getHostAddress() : host, this.serverConf.getIntValue("port"));
|
||||||
this.sncpGroup = application.globalNodes.get(this.sncpAddress);
|
this.sncpGroup = application.globalNodes.get(this.sncpAddress);
|
||||||
if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found <group> info");
|
if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found <group> info");
|
||||||
if (server != null) this.nodeProtocol = server.getProtocol();
|
|
||||||
}
|
}
|
||||||
initGroup();
|
|
||||||
if (this.sncpAddress != null) this.factory.register(RESNAME_SERVER_ADDR, this.sncpAddress);
|
if (this.sncpAddress != null) this.factory.register(RESNAME_SERVER_ADDR, this.sncpAddress); //单点服务不会有 sncpAddress、sncpGroup
|
||||||
if (this.sncpGroup != null) this.factory.register(RESNAME_SERVER_GROUP, this.sncpGroup);
|
if (this.sncpGroup != null) this.factory.register(RESNAME_SERVER_GROUP, this.sncpGroup);
|
||||||
{
|
{
|
||||||
//设置root文件夹
|
//设置root文件夹
|
||||||
@@ -137,8 +127,9 @@ public abstract class NodeServer {
|
|||||||
Server.loadLib(logger, config.getValue("lib", "") + ";" + homepath + "/lib/*;" + homepath + "/classes");
|
Server.loadLib(logger, config.getValue("lib", "") + ";" + homepath + "/lib/*;" + homepath + "/classes");
|
||||||
if (server != null) server.init(config);
|
if (server != null) server.init(config);
|
||||||
}
|
}
|
||||||
initResource();
|
|
||||||
//prepare();
|
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
|
||||||
|
|
||||||
ClassFilter<Servlet> servletFilter = createServletClassFilter();
|
ClassFilter<Servlet> servletFilter = createServletClassFilter();
|
||||||
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
||||||
long s = System.currentTimeMillis();
|
long s = System.currentTimeMillis();
|
||||||
@@ -166,25 +157,23 @@ public abstract class NodeServer {
|
|||||||
DataSource source = new DataDefaultSource(resourceName);
|
DataSource source = new DataDefaultSource(resourceName);
|
||||||
application.dataSources.add(source);
|
application.dataSources.add(source);
|
||||||
regFactory.register(resourceName, DataSource.class, source);
|
regFactory.register(resourceName, DataSource.class, source);
|
||||||
List<Transport> sameGroupTransports = sncpSameGroupTransports;
|
Transport sameGroupTransport = null;
|
||||||
List<Transport> diffGroupTransports = sncpDiffGroupTransports;
|
List<Transport> diffGroupTransports = null;
|
||||||
try {
|
try {
|
||||||
Field ts = src.getClass().getDeclaredField("_sameGroupTransports");
|
Field ts = src.getClass().getDeclaredField("_sameGroupTransport");
|
||||||
ts.setAccessible(true);
|
ts.setAccessible(true);
|
||||||
Transport[] lts = (Transport[]) ts.get(src);
|
sameGroupTransport = (Transport) ts.get(src);
|
||||||
sameGroupTransports = Arrays.asList(lts);
|
|
||||||
|
|
||||||
ts = src.getClass().getDeclaredField("_diffGroupTransports");
|
ts = src.getClass().getDeclaredField("_diffGroupTransports");
|
||||||
ts.setAccessible(true);
|
ts.setAccessible(true);
|
||||||
lts = (Transport[]) ts.get(src);
|
diffGroupTransports = Arrays.asList((Transport[]) ts.get(src));
|
||||||
diffGroupTransports = Arrays.asList(lts);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//src 不含 MultiRun 方法
|
//src 不含 MultiRun 方法
|
||||||
}
|
}
|
||||||
if (factory.find(resourceName, DataCacheListener.class) == null) {
|
if (factory.find(resourceName, DataCacheListener.class) == null) {
|
||||||
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), DataCacheListenerService.class, this.sncpAddress, sncpDefaultGroups, sameGroupTransports, diffGroupTransports);
|
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), DataCacheListenerService.class, this.sncpAddress, sameGroupTransport, diffGroupTransports);
|
||||||
regFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
regFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
||||||
ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, resourceName, sncpGroup, sncpDefaultGroups, null);
|
ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, resourceName, sncpGroup, null, null);
|
||||||
localServiceWrappers.add(wrapper);
|
localServiceWrappers.add(wrapper);
|
||||||
if (consumer != null) consumer.accept(wrapper);
|
if (consumer != null) consumer.accept(wrapper);
|
||||||
rf.inject(cacheListenerService, self);
|
rf.inject(cacheListenerService, self);
|
||||||
@@ -199,22 +188,20 @@ public abstract class NodeServer {
|
|||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 CacheSource
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 CacheSource
|
||||||
List<Transport> sameGroupTransports = sncpSameGroupTransports;
|
Transport sameGroupTransport = null;
|
||||||
List<Transport> diffGroupTransports = sncpDiffGroupTransports;
|
List<Transport> diffGroupTransports = null;
|
||||||
try {
|
try {
|
||||||
Field ts = src.getClass().getDeclaredField("_sameGroupTransports");
|
Field ts = src.getClass().getDeclaredField("_sameGroupTransport");
|
||||||
ts.setAccessible(true);
|
ts.setAccessible(true);
|
||||||
Transport[] lts = (Transport[]) ts.get(src);
|
sameGroupTransport = (Transport) ts.get(src);
|
||||||
sameGroupTransports = Arrays.asList(lts);
|
|
||||||
|
|
||||||
ts = src.getClass().getDeclaredField("_diffGroupTransports");
|
ts = src.getClass().getDeclaredField("_diffGroupTransports");
|
||||||
ts.setAccessible(true);
|
ts.setAccessible(true);
|
||||||
lts = (Transport[]) ts.get(src);
|
diffGroupTransports = Arrays.asList((Transport[]) ts.get(src));
|
||||||
diffGroupTransports = Arrays.asList(lts);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//src 不含 MultiRun 方法
|
//src 不含 MultiRun 方法
|
||||||
}
|
}
|
||||||
CacheSourceService source = Sncp.createLocalService(resourceName, getExecutor(), CacheSourceService.class, this.sncpAddress, sncpDefaultGroups, sameGroupTransports, diffGroupTransports);
|
CacheSourceService source = Sncp.createLocalService(resourceName, getExecutor(), CacheSourceService.class, this.sncpAddress, sameGroupTransport, diffGroupTransports);
|
||||||
Type genericType = field.getGenericType();
|
Type genericType = field.getGenericType();
|
||||||
ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null;
|
ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null;
|
||||||
Type valType = pt == null ? null : pt.getActualTypeArguments()[1];
|
Type valType = pt == null ? null : pt.getActualTypeArguments()[1];
|
||||||
@@ -232,7 +219,7 @@ public abstract class NodeServer {
|
|||||||
sncpServer = (NodeSncpServer) node;
|
sncpServer = (NodeSncpServer) node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, getSncpGroup(), sncpDefaultGroups, null);
|
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, getSncpGroup(), null, null);
|
||||||
sncpServer.getSncpServer().addService(wrapper);
|
sncpServer.getSncpServer().addService(wrapper);
|
||||||
}
|
}
|
||||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
logger.fine("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||||
@@ -242,120 +229,37 @@ public abstract class NodeServer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initGroup() {
|
|
||||||
final AnyValue[] services = this.nodeConf.getAnyValues("services");
|
|
||||||
final String[] groups = services.length < 1 ? new String[]{""} : services[0].getValue("groups", "").split(";");
|
|
||||||
this.sncpDefaultGroups.addAll(Arrays.asList(groups));
|
|
||||||
if (!isSNCP()) {
|
|
||||||
NodeSncpServer sncpServer = null;
|
|
||||||
for (NodeServer node : application.servers) {
|
|
||||||
if (!node.isSNCP()) continue;
|
|
||||||
if (!this.sncpDefaultGroups.contains(node.sncpGroup)) continue;
|
|
||||||
sncpServer = (NodeSncpServer) node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (sncpServer == null && (groups.length == 1 && groups[0].isEmpty())) {
|
|
||||||
for (NodeServer node : application.servers) {
|
|
||||||
if (!node.isSNCP()) continue;
|
|
||||||
sncpServer = (NodeSncpServer) node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sncpServer != null) {
|
|
||||||
this.sncpAddress = sncpServer.getSncpAddress();
|
|
||||||
this.sncpGroup = sncpServer.getSncpGroup();
|
|
||||||
this.sncpDefaultGroups.clear();
|
|
||||||
this.sncpDefaultGroups.addAll(sncpServer.sncpDefaultGroups);
|
|
||||||
this.sncpSameGroupTransports.addAll(sncpServer.sncpSameGroupTransports);
|
|
||||||
this.sncpDiffGroupTransports.addAll(sncpServer.sncpDiffGroupTransports);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Set<InetSocketAddress> sameGroupAddrs = application.findGlobalGroup(this.sncpGroup);
|
|
||||||
final Map<String, Set<InetSocketAddress>> diffGroupAddrs = new HashMap<>();
|
|
||||||
for (String groupitem : groups) {
|
|
||||||
final Set<InetSocketAddress> addrs = application.findGlobalGroup(groupitem);
|
|
||||||
if (addrs == null || groupitem.equals(this.sncpGroup)) continue;
|
|
||||||
diffGroupAddrs.put(groupitem, addrs);
|
|
||||||
}
|
|
||||||
if (sameGroupAddrs != null) {
|
|
||||||
sameGroupAddrs.remove(this.sncpAddress);
|
|
||||||
for (InetSocketAddress iaddr : sameGroupAddrs) {
|
|
||||||
sncpSameGroupTransports.add(loadTransport(this.sncpGroup, getNodeProtocol(), iaddr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diffGroupAddrs.forEach((k, v) -> sncpDiffGroupTransports.add(loadTransport(k, getNodeProtocol(), v)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadService(ClassFilter serviceFilter) throws Exception {
|
protected void loadService(ClassFilter serviceFilter) throws Exception {
|
||||||
if (serviceFilter == null) return;
|
if (serviceFilter == null) return;
|
||||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
final Set<FilterEntry<Service>> entrys = serviceFilter.getFilterEntrys();
|
final Set<FilterEntry<Service>> entrys = serviceFilter.getFilterEntrys();
|
||||||
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : factory;
|
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : factory;
|
||||||
final Set<InetSocketAddress> sg = application.findGlobalGroup(this.sncpGroup);
|
|
||||||
for (FilterEntry<Service> entry : entrys) { //service实现类
|
for (FilterEntry<Service> entry : entrys) { //service实现类
|
||||||
final Class<? extends Service> type = entry.getType();
|
final Class<? extends Service> type = entry.getType();
|
||||||
if (Modifier.isFinal(type.getModifiers())) continue;
|
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
|
||||||
if (!Modifier.isPublic(type.getModifiers())) continue;
|
if (!Modifier.isPublic(type.getModifiers())) continue;
|
||||||
if (!isSNCP() && factory.find(entry.getName(), type) != null) continue;
|
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
||||||
final Set<InetSocketAddress> sameGroupAddrs = new LinkedHashSet<>();
|
if (!isSNCP() && factory.find(entry.getName(), type) != null) continue; //非SNCP的Server加载Service时需要判断是否在SNCP的Server已经加载过了。
|
||||||
final Map<String, Set<InetSocketAddress>> diffGroupAddrs = new HashMap<>();
|
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
|
||||||
final HashSet<String> groups = entry.getGroups();
|
if (groups.isEmpty() && isSNCP()) groups.add(this.sncpGroup);
|
||||||
for (String g : groups) {
|
|
||||||
if (g.isEmpty()) continue;
|
final boolean localed = this.sncpAddress == null //非SNCP的Server,通常是单点服务
|
||||||
if (g.equals(this.sncpGroup) && sg != null) sameGroupAddrs.addAll(sg);
|
|| groups.contains(this.sncpGroup) //本地IP含在内的
|
||||||
Set<InetSocketAddress> set = application.findGlobalGroup(g);
|
|| type.getAnnotation(LocalService.class) != null;//本地模式
|
||||||
if (set == null) throw new RuntimeException(type.getName() + " has illegal group (" + groups + ")");
|
|
||||||
if (!g.equals(this.sncpGroup)) {
|
|
||||||
diffGroupAddrs.put(g, set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<Transport> diffGroupTransports = new ArrayList<>();
|
|
||||||
diffGroupAddrs.forEach((k, v) -> diffGroupTransports.add(loadTransport(k, server.getProtocol(), v)));
|
|
||||||
final boolean localed = (sameGroupAddrs.isEmpty() && diffGroupAddrs.isEmpty()) || sameGroupAddrs.contains(this.sncpAddress) || type.getAnnotation(LocalService.class) != null;//本地模式
|
|
||||||
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||||
final ServiceResource st = type.getAnnotation(ServiceResource.class);
|
|
||||||
final Class<? extends Service> resType = st == null ? type : st.value();
|
Service service;
|
||||||
if (st != null && (!isSNCP() && factory.find(entry.getName(), resType) != null)) continue;
|
|
||||||
ServiceWrapper wrapper;
|
|
||||||
if (localed) { //本地模式
|
if (localed) { //本地模式
|
||||||
sameGroupAddrs.remove(this.sncpAddress);
|
service = Sncp.createLocalService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(this.sncpGroup), loadTransports(groups));
|
||||||
List<Transport> sameGroupTransports = new ArrayList<>();
|
|
||||||
for (InetSocketAddress iaddr : sameGroupAddrs) {
|
|
||||||
Set<InetSocketAddress> tset = new HashSet<>();
|
|
||||||
tset.add(iaddr);
|
|
||||||
sameGroupTransports.add(loadTransport(this.sncpGroup, server.getProtocol(), tset));
|
|
||||||
}
|
|
||||||
Service service = Sncp.createLocalService(entry.getName(), getExecutor(), type, this.sncpAddress, groups, sameGroupTransports, diffGroupTransports);
|
|
||||||
wrapper = new ServiceWrapper(resType, service, this.sncpGroup, entry);
|
|
||||||
if (fine) logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + service);
|
|
||||||
} else {
|
} else {
|
||||||
sameGroupAddrs.remove(this.sncpAddress);
|
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(groups));
|
||||||
StringBuilder g = new StringBuilder();
|
|
||||||
diffGroupAddrs.forEach((k, v) -> {
|
|
||||||
if (g.length() > 0) g.append(';');
|
|
||||||
g.append(k);
|
|
||||||
sameGroupAddrs.addAll(v);
|
|
||||||
});
|
|
||||||
if (sameGroupAddrs.isEmpty()) throw new RuntimeException(type.getName() + " has no remote address on group (" + groups + ")");
|
|
||||||
Service service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, groups, loadTransport(g.toString(), server.getProtocol(), sameGroupAddrs));
|
|
||||||
wrapper = new ServiceWrapper(resType, service, "", entry);
|
|
||||||
if (fine) logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + service);
|
|
||||||
}
|
}
|
||||||
|
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? this.sncpGroup : null, groups, entry.getProperty());
|
||||||
|
if (fine) logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||||
if (factory.find(wrapper.getName(), wrapper.getType()) == null) {
|
if (factory.find(wrapper.getName(), wrapper.getType()) == null) {
|
||||||
regFactory.register(wrapper.getName(), wrapper.getType(), wrapper.getService());
|
regFactory.register(wrapper.getName(), wrapper.getService());
|
||||||
if (wrapper.getService() instanceof DataSource) {
|
|
||||||
regFactory.register(wrapper.getName(), DataSource.class, wrapper.getService());
|
|
||||||
} else if (wrapper.getService() instanceof CacheSource) {
|
|
||||||
regFactory.register(wrapper.getName(), CacheSource.class, wrapper.getService());
|
|
||||||
} else if (wrapper.getService() instanceof DataCacheListener) {
|
|
||||||
regFactory.register(wrapper.getName(), DataCacheListener.class, wrapper.getService());
|
|
||||||
} else if (wrapper.getService() instanceof DataSQLListener) {
|
|
||||||
regFactory.register(wrapper.getName(), DataSQLListener.class, wrapper.getService());
|
|
||||||
} else if (wrapper.getService() instanceof WebSocketNode) {
|
|
||||||
regFactory.register(wrapper.getName(), WebSocketNode.class, wrapper.getService());
|
|
||||||
}
|
|
||||||
if (wrapper.isRemote()) {
|
if (wrapper.isRemote()) {
|
||||||
remoteServiceWrappers.add(wrapper);
|
remoteServiceWrappers.add(wrapper);
|
||||||
} else {
|
} else {
|
||||||
@@ -392,30 +296,69 @@ public abstract class NodeServer {
|
|||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Transport loadTransport(String group, String protocol, InetSocketAddress addr) {
|
protected List<Transport> loadTransports(final HashSet<String> groups) {
|
||||||
if (addr == null) return null;
|
if (groups == null) return null;
|
||||||
Set<InetSocketAddress> set = new HashSet<>();
|
final List<Transport> transports = new ArrayList<>();
|
||||||
set.add(addr);
|
for (String group : groups) {
|
||||||
return loadTransport(group, protocol, set);
|
transports.add(loadTransport(group));
|
||||||
|
}
|
||||||
|
return transports;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Transport loadTransport(String group, String protocol, Set<InetSocketAddress> addrs) {
|
protected Transport loadTransport(final HashSet<String> groups) {
|
||||||
Transport transport = null;
|
if (groups == null || groups.isEmpty()) return null;
|
||||||
if (!addrs.isEmpty()) {
|
List<String> tmpgroup = new ArrayList<>(groups);
|
||||||
synchronized (application.transports) {
|
Collections.sort(tmpgroup); //按字母排列顺序
|
||||||
for (Transport tran : application.transports) {
|
boolean flag = false;
|
||||||
if (tran.match(addrs)) {
|
StringBuilder sb = new StringBuilder();
|
||||||
transport = tran;
|
for (String g : tmpgroup) {
|
||||||
break;
|
if (flag) sb.append(';');
|
||||||
}
|
sb.append(g);
|
||||||
}
|
flag = true;
|
||||||
if (transport == null) {
|
}
|
||||||
transport = new Transport(group + "_" + application.transports.size(), protocol, application.getWatchFactory(), 32, addrs);
|
final String groupid = sb.toString();
|
||||||
logger.info(transport + " created");
|
Transport transport = application.transports.get(groupid);
|
||||||
application.transports.add(transport);
|
if (transport != null) return transport;
|
||||||
}
|
final List<Transport> transports = new ArrayList<>();
|
||||||
|
for (String group : groups) {
|
||||||
|
transports.add(loadTransport(group));
|
||||||
|
}
|
||||||
|
Set<InetSocketAddress> addrs = new HashSet();
|
||||||
|
for (Transport t : transports) {
|
||||||
|
for (InetSocketAddress addr : t.getRemoteAddresses()) {
|
||||||
|
addrs.add(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Transport first = transports.get(0);
|
||||||
|
Transport newTransport = new Transport(groupid, application.findGroupProtocol(first.getName()), application.getWatchFactory(),
|
||||||
|
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||||
|
synchronized (application.transports) {
|
||||||
|
transport = application.transports.get(groupid);
|
||||||
|
if (transport == null) {
|
||||||
|
transport = newTransport;
|
||||||
|
application.transports.put(groupid, transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transport loadTransport(final String group) {
|
||||||
|
if (group == null) return null;
|
||||||
|
Transport transport;
|
||||||
|
synchronized (application.transports) {
|
||||||
|
transport = application.transports.get(group);
|
||||||
|
if (transport != null) {
|
||||||
|
if (this.sncpAddress != null && !this.sncpAddress.equals(transport.getClientAddress())) {
|
||||||
|
throw new RuntimeException(transport + "repeat create on newClientAddress = " + this.sncpAddress + ", oldClientAddress = " + transport.getClientAddress());
|
||||||
|
}
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
Set<InetSocketAddress> addrs = application.findGlobalGroup(group);
|
||||||
|
if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> ");
|
||||||
|
transport = new Transport(group, application.findGroupProtocol(group), application.getWatchFactory(),
|
||||||
|
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||||
|
application.transports.put(group, transport);
|
||||||
|
}
|
||||||
return transport;
|
return transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,13 +372,17 @@ public abstract class NodeServer {
|
|||||||
Class inter, Class<? extends Annotation> ref2, String properties, String property) {
|
Class inter, Class<? extends Annotation> ref2, String properties, String property) {
|
||||||
ClassFilter cf = new ClassFilter(ref, inter, null);
|
ClassFilter cf = new ClassFilter(ref, inter, null);
|
||||||
if (properties == null && properties == null) return cf;
|
if (properties == null && properties == null) return cf;
|
||||||
if (this.nodeConf == null) return cf;
|
if (this.serverConf == null) return cf;
|
||||||
AnyValue[] proplist = this.nodeConf.getAnyValues(properties);
|
AnyValue[] proplist = this.serverConf.getAnyValues(properties);
|
||||||
if (proplist == null || proplist.length < 1) return cf;
|
if (proplist == null || proplist.length < 1) return cf;
|
||||||
cf = null;
|
cf = null;
|
||||||
for (AnyValue list : proplist) {
|
for (AnyValue list : proplist) {
|
||||||
DefaultAnyValue prop = null;
|
DefaultAnyValue prop = null;
|
||||||
String sc = list.getValue("groups");
|
String sc = list.getValue("groups");
|
||||||
|
if (sc != null) {
|
||||||
|
sc = sc.trim();
|
||||||
|
if (sc.endsWith(";")) sc = sc.substring(0, sc.length() - 1);
|
||||||
|
}
|
||||||
if (sc == null) sc = localGroup;
|
if (sc == null) sc = localGroup;
|
||||||
if (sc != null) {
|
if (sc != null) {
|
||||||
prop = new AnyValue.DefaultAnyValue();
|
prop = new AnyValue.DefaultAnyValue();
|
||||||
@@ -496,10 +443,6 @@ public abstract class NodeServer {
|
|||||||
return sncpGroup;
|
return sncpGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNodeProtocol() {
|
|
||||||
return nodeProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import org.redkale.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@NodeProtocol({"SNCP"})
|
@NodeProtocol({"SNCP"})
|
||||||
@@ -22,7 +24,7 @@ public final class NodeSncpServer extends NodeServer {
|
|||||||
private final SncpServer sncpServer;
|
private final SncpServer sncpServer;
|
||||||
|
|
||||||
public NodeSncpServer(Application application, AnyValue serconf) {
|
public NodeSncpServer(Application application, AnyValue serconf) {
|
||||||
super(application, application.getResourceFactory().createChild(), createServer(application, serconf));
|
super(application, createServer(application, serconf));
|
||||||
this.sncpServer = (SncpServer) this.server;
|
this.sncpServer = (SncpServer) this.server;
|
||||||
this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x);
|
this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import org.redkale.watch.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public abstract class Server {
|
public abstract class Server {
|
||||||
@@ -49,7 +51,7 @@ public abstract class Server {
|
|||||||
|
|
||||||
protected ProtocolServer serverChannel;
|
protected ProtocolServer serverChannel;
|
||||||
|
|
||||||
protected int capacity;
|
protected int bufferCapacity;
|
||||||
|
|
||||||
protected int threads;
|
protected int threads;
|
||||||
|
|
||||||
@@ -82,8 +84,8 @@ public abstract class Server {
|
|||||||
this.backlog = config.getIntValue("backlog", 8 * 1024);
|
this.backlog = config.getIntValue("backlog", 8 * 1024);
|
||||||
this.readTimeoutSecond = config.getIntValue("readTimeoutSecond", 0);
|
this.readTimeoutSecond = config.getIntValue("readTimeoutSecond", 0);
|
||||||
this.writeTimeoutSecond = config.getIntValue("writeTimeoutSecond", 0);
|
this.writeTimeoutSecond = config.getIntValue("writeTimeoutSecond", 0);
|
||||||
this.capacity = config.getIntValue("capacity", 8 * 1024);
|
|
||||||
this.maxbody = config.getIntValue("maxbody", 64 * 1024);
|
this.maxbody = config.getIntValue("maxbody", 64 * 1024);
|
||||||
|
this.bufferCapacity = config.getIntValue("bufferCapacity", 8 * 1024);
|
||||||
this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 16);
|
this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 16);
|
||||||
this.bufferPoolSize = config.getIntValue("bufferPoolSize", Runtime.getRuntime().availableProcessors() * 512);
|
this.bufferPoolSize = config.getIntValue("bufferPoolSize", Runtime.getRuntime().availableProcessors() * 512);
|
||||||
this.responsePoolSize = config.getIntValue("responsePoolSize", Runtime.getRuntime().availableProcessors() * 256);
|
this.responsePoolSize = config.getIntValue("responsePoolSize", Runtime.getRuntime().availableProcessors() * 256);
|
||||||
@@ -127,7 +129,7 @@ public abstract class Server {
|
|||||||
serverChannel.accept();
|
serverChannel.accept();
|
||||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
logger.info(threadName + this.getClass().getSimpleName() + "." + protocol + " listen: " + address
|
logger.info(threadName + this.getClass().getSimpleName() + "." + protocol + " listen: " + address
|
||||||
+ ", threads: " + threads + ", bufferCapacity: " + capacity + ", bufferPoolSize: " + bufferPoolSize + ", responsePoolSize: " + responsePoolSize
|
+ ", threads: " + threads + ", bufferCapacity: " + bufferCapacity + ", bufferPoolSize: " + bufferPoolSize + ", responsePoolSize: " + responsePoolSize
|
||||||
+ ", started in " + (System.currentTimeMillis() - context.getServerStartTime()) + " ms");
|
+ ", started in " + (System.currentTimeMillis() - context.getServerStartTime()) + " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import java.nio.*;
|
|||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.*;
|
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
import org.redkale.watch.*;
|
import org.redkale.watch.*;
|
||||||
@@ -42,97 +41,104 @@ public final class Transport {
|
|||||||
supportTcpNoDelay = tcpNoDelay;
|
supportTcpNoDelay = tcpNoDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final String name;
|
protected final String name; //即<group>的name属性
|
||||||
|
|
||||||
protected final int bufferPoolSize;
|
|
||||||
|
|
||||||
protected final int bufferCapacity;
|
|
||||||
|
|
||||||
protected final boolean tcp;
|
protected final boolean tcp;
|
||||||
|
|
||||||
protected final String protocol;
|
protected final String protocol;
|
||||||
|
|
||||||
|
protected final WatchFactory watch;
|
||||||
|
|
||||||
protected final AsynchronousChannelGroup group;
|
protected final AsynchronousChannelGroup group;
|
||||||
|
|
||||||
protected final InetSocketAddress[] remoteAddres;
|
protected final InetSocketAddress clientAddress;
|
||||||
|
|
||||||
|
protected InetSocketAddress[] remoteAddres = new InetSocketAddress[0];
|
||||||
|
|
||||||
protected final ObjectPool<ByteBuffer> bufferPool;
|
protected final ObjectPool<ByteBuffer> bufferPool;
|
||||||
|
|
||||||
protected final ConcurrentHashMap<SocketAddress, BlockingQueue<AsyncConnection>> connPool = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<SocketAddress, BlockingQueue<AsyncConnection>> connPool = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public Transport(Transport transport, InetSocketAddress localAddress, Collection<Transport> transports) {
|
public Transport(String name, WatchFactory watch, final ObjectPool<ByteBuffer> transportBufferPool,
|
||||||
this(transport.name, transport.protocol, null, transport.bufferPoolSize, parse(localAddress, transports));
|
final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
|
||||||
|
this(name, DEFAULT_PROTOCOL, watch, transportBufferPool, transportChannelGroup, clientAddress, addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transport(String name, WatchFactory watch, int bufferPoolSize, Collection<InetSocketAddress> addresses) {
|
public Transport(String name, String protocol, WatchFactory watch, final ObjectPool<ByteBuffer> transportBufferPool,
|
||||||
this(name, DEFAULT_PROTOCOL, watch, bufferPoolSize, addresses);
|
final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
|
||||||
}
|
|
||||||
|
|
||||||
public Transport(String name, String protocol, WatchFactory watch, int bufferPoolSize, Collection<InetSocketAddress> addresses) {
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.watch = watch;
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
this.tcp = "TCP".equalsIgnoreCase(protocol);
|
this.tcp = "TCP".equalsIgnoreCase(protocol);
|
||||||
this.bufferPoolSize = bufferPoolSize;
|
this.group = transportChannelGroup;
|
||||||
this.bufferCapacity = 8192;
|
this.bufferPool = transportBufferPool;
|
||||||
AsynchronousChannelGroup g = null;
|
this.clientAddress = clientAddress;
|
||||||
try {
|
updateRemoteAddresses(addresses);
|
||||||
final AtomicInteger counter = new AtomicInteger();
|
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8, (Runnable r) -> {
|
|
||||||
Thread t = new Thread(r);
|
|
||||||
t.setDaemon(true);
|
|
||||||
t.setName("Transport-" + name + "-Thread-" + counter.incrementAndGet());
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
g = AsynchronousChannelGroup.withCachedThreadPool(executor, 1);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
this.group = g;
|
|
||||||
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + "-" + name + "-" + protocol + ".Buffer.creatCounter");
|
|
||||||
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + "-" + name + "-" + protocol + ".Buffer.cycleCounter");
|
|
||||||
final int rcapacity = bufferCapacity;
|
|
||||||
this.bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, bufferPoolSize,
|
|
||||||
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
|
|
||||||
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
|
|
||||||
e.clear();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
this.remoteAddres = addresses.toArray(new InetSocketAddress[addresses.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<InetSocketAddress> parse(InetSocketAddress addr, Collection<Transport> transports) {
|
public Transport(final Collection<Transport> transports) {
|
||||||
final Set<InetSocketAddress> set = new LinkedHashSet<>();
|
Transport first = null;
|
||||||
|
List<String> tmpgroup = new ArrayList<>();
|
||||||
for (Transport t : transports) {
|
for (Transport t : transports) {
|
||||||
set.addAll(Arrays.asList(t.remoteAddres));
|
if (first == null) first = t;
|
||||||
|
tmpgroup.add(t.name);
|
||||||
}
|
}
|
||||||
set.remove(addr);
|
Collections.sort(tmpgroup); //按字母排列顺序
|
||||||
return set;
|
boolean flag = false;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String g : tmpgroup) {
|
||||||
|
if (flag) sb.append(';');
|
||||||
|
sb.append(g);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
this.name = sb.toString();
|
||||||
|
this.watch = first.watch;
|
||||||
|
this.protocol = first.protocol;
|
||||||
|
this.tcp = "TCP".equalsIgnoreCase(first.protocol);
|
||||||
|
this.group = first.group;
|
||||||
|
this.bufferPool = first.bufferPool;
|
||||||
|
this.clientAddress = first.clientAddress;
|
||||||
|
Set<InetSocketAddress> addrs = new HashSet();
|
||||||
|
for (Transport t : transports) {
|
||||||
|
for (InetSocketAddress addr : t.getRemoteAddresses()) {
|
||||||
|
addrs.add(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateRemoteAddresses(addrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final InetSocketAddress[] updateRemoteAddresses(final Collection<InetSocketAddress> addresses) {
|
||||||
|
InetSocketAddress[] oldAddresses = this.remoteAddres;
|
||||||
|
List<InetSocketAddress> list = new ArrayList<>();
|
||||||
|
if (addresses != null) {
|
||||||
|
for (InetSocketAddress addr : addresses) {
|
||||||
|
if (clientAddress != null && clientAddress.equals(addr)) continue;
|
||||||
|
list.add(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.remoteAddres = list.toArray(new InetSocketAddress[list.size()]);
|
||||||
|
return oldAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
connPool.forEach((k, v) -> v.forEach(c -> c.dispose()));
|
connPool.forEach((k, v) -> v.forEach(c -> c.dispose()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean match(Collection<InetSocketAddress> addrs) {
|
public InetSocketAddress getClientAddress() {
|
||||||
if (addrs == null) return false;
|
return clientAddress;
|
||||||
if (addrs.size() != this.remoteAddres.length) return false;
|
|
||||||
for (InetSocketAddress addr : this.remoteAddres) {
|
|
||||||
if (!addrs.contains(addr)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress[] getRemoteAddress() {
|
public InetSocketAddress[] getRemoteAddresses() {
|
||||||
return remoteAddres;
|
return remoteAddres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Transport.class.getSimpleName() + "{name=" + name + ",protocol=" + protocol + ",remoteAddres=" + Arrays.toString(remoteAddres) + "}";
|
return Transport.class.getSimpleName() + "{name = " + name + ", protocol = " + protocol + ", clientAddress = " + clientAddress + ", remoteAddres = " + Arrays.toString(remoteAddres) + "}";
|
||||||
}
|
|
||||||
|
|
||||||
public int getBufferCapacity() {
|
|
||||||
return bufferCapacity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer pollBuffer() {
|
public ByteBuffer pollBuffer() {
|
||||||
@@ -207,7 +213,7 @@ public final class Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerConnection(final boolean forceClose, AsyncConnection conn) {
|
public void offerConnection(final boolean forceClose, AsyncConnection conn) {
|
||||||
if (!forceClose && conn.isTCP()) { //暂时每次都关闭
|
if (!forceClose && conn.isTCP()) {
|
||||||
if (conn.isOpen()) {
|
if (conn.isOpen()) {
|
||||||
BlockingQueue<AsyncConnection> queue = connPool.get(conn.getRemoteAddress());
|
BlockingQueue<AsyncConnection> queue = connPool.get(conn.getRemoteAddress());
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public final class HttpServer extends Server {
|
|||||||
final int port = this.address.getPort();
|
final int port = this.address.getPort();
|
||||||
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.creatCounter");
|
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.creatCounter");
|
||||||
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.cycleCounter");
|
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.cycleCounter");
|
||||||
final int rcapacity = Math.max(this.capacity, 16 * 1024 + 8); //兼容 HTTP 2.0
|
final int rcapacity = Math.max(this.bufferCapacity, 16 * 1024 + 8); //兼容 HTTP 2.0
|
||||||
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
|
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
|
||||||
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
|
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
|
||||||
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
|
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import javax.annotation.*;
|
import javax.annotation.*;
|
||||||
|
import org.redkale.boot.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.source.*;
|
import org.redkale.source.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
@@ -29,7 +30,7 @@ public abstract class WebSocketNode {
|
|||||||
|
|
||||||
protected final boolean finest = logger.isLoggable(Level.FINEST);
|
protected final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
|
|
||||||
@Resource(name = "SERVER_ADDR")
|
@Resource(name = Application.RESNAME_SERVER_GROUP)
|
||||||
protected InetSocketAddress localSncpAddress; //为SncpServer的服务address
|
protected InetSocketAddress localSncpAddress; //为SncpServer的服务address
|
||||||
|
|
||||||
@DynRemote
|
@DynRemote
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ package org.redkale.net.sncp;
|
|||||||
import org.redkale.service.Service;
|
import org.redkale.service.Service;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service对象的封装类
|
* Service对象的封装类
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> Service的子类
|
* @param <T> Service的子类
|
||||||
*/
|
*/
|
||||||
@@ -25,26 +27,26 @@ public final class ServiceWrapper<T extends Service> {
|
|||||||
|
|
||||||
private final AnyValue conf;
|
private final AnyValue conf;
|
||||||
|
|
||||||
private final String group;
|
private final String sncpGroup; //自身的组节点名 可能为null
|
||||||
|
|
||||||
private final Set<String> groups;
|
private final Set<String> groups; //所有的组节点,包含自身
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private final boolean remote;
|
private final boolean remote;
|
||||||
|
|
||||||
public ServiceWrapper(Class<T> type, T service, String group, ClassFilter.FilterEntry<Service> entry) {
|
private final Class[] resTypes;
|
||||||
this(type, service, entry.getName(), group, entry.getGroups(), entry.getProperty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceWrapper(Class<T> type, T service, String name, String group, Set<String> groups, AnyValue conf) {
|
public ServiceWrapper(Class<T> type, T service, String name, String sncpGroup, Set<String> groups, AnyValue conf) {
|
||||||
this.type = type == null ? (Class<T>) service.getClass() : type;
|
this.type = type == null ? (Class<T>) service.getClass() : type;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
this.conf = conf;
|
this.conf = conf;
|
||||||
this.group = group;
|
this.sncpGroup = sncpGroup;
|
||||||
this.groups = groups;
|
this.groups = groups;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.remote = Sncp.isRemote(service);
|
this.remote = Sncp.isRemote(service);
|
||||||
|
ResourceType rty = service.getClass().getAnnotation(ResourceType.class);
|
||||||
|
this.resTypes = rty == null ? new Class[]{this.type} : rty.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,14 +55,14 @@ public final class ServiceWrapper<T extends Service> {
|
|||||||
if (obj == null) return false;
|
if (obj == null) return false;
|
||||||
if (!(obj instanceof ServiceWrapper)) return false;
|
if (!(obj instanceof ServiceWrapper)) return false;
|
||||||
ServiceWrapper other = (ServiceWrapper) obj;
|
ServiceWrapper other = (ServiceWrapper) obj;
|
||||||
return (this.type.equals(other.type) && this.remote == other.remote && this.name.equals(other.name) && this.group.equals(other.group));
|
return (this.type.equals(other.type) && this.remote == other.remote && this.name.equals(other.name) && Objects.equals(this.sncpGroup, other.sncpGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = 3;
|
int hash = 3;
|
||||||
hash = 67 * hash + Objects.hashCode(this.type);
|
hash = 67 * hash + Objects.hashCode(this.type);
|
||||||
hash = 67 * hash + Objects.hashCode(this.group);
|
hash = 67 * hash + Objects.hashCode(this.sncpGroup);
|
||||||
hash = 67 * hash + Objects.hashCode(this.name);
|
hash = 67 * hash + Objects.hashCode(this.name);
|
||||||
hash = 67 * hash + (this.remote ? 1 : 0);
|
hash = 67 * hash + (this.remote ? 1 : 0);
|
||||||
return hash;
|
return hash;
|
||||||
@@ -70,6 +72,10 @@ public final class ServiceWrapper<T extends Service> {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Class[] getResTypes() {
|
||||||
|
return resTypes;
|
||||||
|
}
|
||||||
|
|
||||||
public Service getService() {
|
public Service getService() {
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import java.net.*;
|
|||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import javax.annotation.*;
|
|
||||||
import jdk.internal.org.objectweb.asm.*;
|
import jdk.internal.org.objectweb.asm.*;
|
||||||
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||||
@@ -34,12 +33,6 @@ import org.redkale.service.DynRemote;
|
|||||||
*/
|
*/
|
||||||
public abstract class Sncp {
|
public abstract class Sncp {
|
||||||
|
|
||||||
//当前SNCP Server的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
|
|
||||||
public static final String RESNAME_SNCP_ADDR = "SNCP_ADDR";
|
|
||||||
|
|
||||||
//当前Service所属的组 类型: Set<String>、String[]
|
|
||||||
public static final String RESNAME_SNCP_GROUPS = "SNCP_GROUPS";
|
|
||||||
|
|
||||||
private static final java.lang.reflect.Type GROUPS_TYPE1 = new TypeToken<Set<String>>() {
|
private static final java.lang.reflect.Type GROUPS_TYPE1 = new TypeToken<Set<String>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
@@ -128,12 +121,13 @@ public abstract class Sncp {
|
|||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
* @Resource(name = "")
|
* @Resource(name = "")
|
||||||
* @SncpDyn(remote = false)
|
* @SncpDyn(remote = false)
|
||||||
|
* @ResourceType({TestService.class})
|
||||||
* public final class _DynLocalTestService extends TestService{
|
* public final class _DynLocalTestService extends TestService{
|
||||||
*
|
*
|
||||||
* @Resource
|
* @Resource
|
||||||
* private BsonConvert _convert;
|
* private BsonConvert _convert;
|
||||||
*
|
*
|
||||||
* private Transport[] _sameGroupTransports;
|
* private Transport _sameGroupTransport;
|
||||||
*
|
*
|
||||||
* private Transport[] _diffGroupTransports;
|
* private Transport[] _diffGroupTransports;
|
||||||
*
|
*
|
||||||
@@ -155,8 +149,8 @@ public abstract class Sncp {
|
|||||||
* public void _createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
|
* public void _createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
|
||||||
* if(selfrunnable) super.createSomeThing(bean);
|
* if(selfrunnable) super.createSomeThing(bean);
|
||||||
* if (_client== null) return;
|
* if (_client== null) return;
|
||||||
* if (samerunnable) _client.remote(_convert, _sameGroupTransports, 0, true, false, false, bean);
|
* if (samerunnable) _client.remoteSameGroup(_convert, _sameGroupTransport, 0, true, false, false, bean);
|
||||||
* if (diffrunnable) _client.remote(_convert, _diffGroupTransports, 0, true, true, false, bean);
|
* if (diffrunnable) _client.remoteDiffGroup(_convert, _diffGroupTransports, 0, true, true, false, bean);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @Override
|
* @Override
|
||||||
@@ -168,8 +162,8 @@ public abstract class Sncp {
|
|||||||
* public String _updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
|
* public String _updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
|
||||||
* String rs = super.updateSomeThing(id);
|
* String rs = super.updateSomeThing(id);
|
||||||
* if (_client== null) return;
|
* if (_client== null) return;
|
||||||
* if (samerunnable) _client.remote(_convert, _sameGroupTransports, 1, true, false, false, id);
|
* if (samerunnable) _client.remoteSameGroup(_convert, _sameGroupTransport, 1, true, false, false, id);
|
||||||
* if (diffrunnable) _client.remote(_convert, _diffGroupTransports, 1, true, true, false, id);
|
* if (diffrunnable) _client.remoteDiffGroup(_convert, _diffGroupTransports, 1, true, true, false, id);
|
||||||
* return rs;
|
* return rs;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@@ -196,6 +190,7 @@ public abstract class Sncp {
|
|||||||
final String clientDesc = Type.getDescriptor(SncpClient.class);
|
final String clientDesc = Type.getDescriptor(SncpClient.class);
|
||||||
final String convertDesc = Type.getDescriptor(BsonConvert.class);
|
final String convertDesc = Type.getDescriptor(BsonConvert.class);
|
||||||
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
||||||
|
final String transportDesc = Type.getDescriptor(Transport.class);
|
||||||
final String transportsDesc = Type.getDescriptor(Transport[].class);
|
final String transportsDesc = Type.getDescriptor(Transport[].class);
|
||||||
ClassLoader loader = Sncp.class.getClassLoader();
|
ClassLoader loader = Sncp.class.getClassLoader();
|
||||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceClass.getSimpleName();
|
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceClass.getSimpleName();
|
||||||
@@ -227,6 +222,22 @@ public abstract class Sncp {
|
|||||||
av0.visit("remote", Boolean.FALSE);
|
av0.visit("remote", Boolean.FALSE);
|
||||||
av0.visitEnd();
|
av0.visitEnd();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
|
||||||
|
{
|
||||||
|
AnnotationVisitor av1 = av0.visitArray("value");
|
||||||
|
ResourceType rty = serviceClass.getAnnotation(ResourceType.class);
|
||||||
|
if (rty == null) {
|
||||||
|
av1.visit(null, Type.getType(Type.getDescriptor(serviceClass)));
|
||||||
|
} else {
|
||||||
|
for (Class cl : rty.value()) {
|
||||||
|
av1.visit(null, Type.getType(Type.getDescriptor(cl)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
}
|
||||||
|
av0.visitEnd();
|
||||||
|
}
|
||||||
if (hasMultiRun) {
|
if (hasMultiRun) {
|
||||||
{
|
{
|
||||||
fv = cw.visitField(ACC_PRIVATE, "_convert", convertDesc, null, null);
|
fv = cw.visitField(ACC_PRIVATE, "_convert", convertDesc, null, null);
|
||||||
@@ -235,7 +246,7 @@ public abstract class Sncp {
|
|||||||
fv.visitEnd();
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
fv = cw.visitField(ACC_PRIVATE, "_sameGroupTransports", transportsDesc, null, null);
|
fv = cw.visitField(ACC_PRIVATE, "_sameGroupTransport", transportDesc, null, null);
|
||||||
fv.visitEnd();
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -437,8 +448,8 @@ public abstract class Sncp {
|
|||||||
mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc);
|
||||||
mv.visitVarInsn(ALOAD, 0); //传递 _convert
|
mv.visitVarInsn(ALOAD, 0); //传递 _convert
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "_convert", convertDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, "_convert", convertDesc);
|
||||||
mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransports
|
mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransport
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "_sameGroupTransports", transportsDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, "_sameGroupTransport", transportDesc);
|
||||||
|
|
||||||
if (index <= 5) { //第几个 SncpAction
|
if (index <= 5) { //第几个 SncpAction
|
||||||
mv.visitInsn(ICONST_0 + index);
|
mv.visitInsn(ICONST_0 + index);
|
||||||
@@ -498,7 +509,7 @@ public abstract class Sncp {
|
|||||||
}
|
}
|
||||||
mv.visitInsn(AASTORE);
|
mv.visitInsn(AASTORE);
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemote" : "remote", "(" + convertDesc + transportsDesc + "I[Ljava/lang/Object;)V", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteSameGroup" : "remoteSameGroup", "(" + convertDesc + transportDesc + "I[Ljava/lang/Object;)V", false);
|
||||||
mv.visitLabel(sameLabel);
|
mv.visitLabel(sameLabel);
|
||||||
//---------------------------- 调用diffrun ---------------------------------
|
//---------------------------- 调用diffrun ---------------------------------
|
||||||
mv.visitVarInsn(ILOAD, 3); //读取 diffrunnable
|
mv.visitVarInsn(ILOAD, 3); //读取 diffrunnable
|
||||||
@@ -570,7 +581,7 @@ public abstract class Sncp {
|
|||||||
}
|
}
|
||||||
mv.visitInsn(AASTORE);
|
mv.visitInsn(AASTORE);
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemote" : "remote", "(" + convertDesc + transportsDesc + "I[Ljava/lang/Object;)V", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteDiffGroup" : "remoteDiffGroup", "(" + convertDesc + transportsDesc + "I[Ljava/lang/Object;)V", false);
|
||||||
mv.visitLabel(diffLabel);
|
mv.visitLabel(diffLabel);
|
||||||
|
|
||||||
if (returnType == void.class) {
|
if (returnType == void.class) {
|
||||||
@@ -669,53 +680,33 @@ public abstract class Sncp {
|
|||||||
* @return Service的本地模式实例
|
* @return Service的本地模式实例
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Service> T createLocalService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass,
|
public static <T extends Service> T createLocalService(final String name, final Consumer<Runnable> executor,
|
||||||
final InetSocketAddress clientAddress, HashSet<String> groups, Collection<Transport> sameGroupTransports, Collection<Transport> diffGroupTransports) {
|
final Class<T> serviceClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection<Transport> diffGroupTransports) {
|
||||||
try {
|
try {
|
||||||
final Class newClazz = createLocalServiceClass(name, serviceClass);
|
final Class newClazz = createLocalServiceClass(name, serviceClass);
|
||||||
T rs = (T) newClazz.newInstance();
|
T rs = (T) newClazz.newInstance();
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
if (sameGroupTransports == null) sameGroupTransports = new ArrayList<>();
|
Service remoteService = null;
|
||||||
if (diffGroupTransports == null) diffGroupTransports = new ArrayList<>();
|
|
||||||
Transport remoteTransport = null;
|
Transport remoteTransport = null;
|
||||||
{
|
{
|
||||||
Class loop = newClazz;
|
Class loop = newClazz;
|
||||||
String[] groupArray = null;
|
|
||||||
do {
|
do {
|
||||||
for (Field field : loop.getDeclaredFields()) {
|
for (Field field : loop.getDeclaredFields()) {
|
||||||
int mod = field.getModifiers();
|
int mod = field.getModifiers();
|
||||||
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) continue;
|
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) continue;
|
||||||
if (field.getAnnotation(DynRemote.class) != null) {
|
if (field.getAnnotation(DynRemote.class) == null) continue;
|
||||||
field.setAccessible(true);
|
if (!field.getType().isAssignableFrom(newClazz)) continue;
|
||||||
if (remoteTransport == null) {
|
|
||||||
List<Transport> list = new ArrayList<>();
|
|
||||||
list.addAll(sameGroupTransports);
|
|
||||||
list.addAll(diffGroupTransports);
|
|
||||||
if (!list.isEmpty()) remoteTransport = new Transport(list.get(0), clientAddress, list);
|
|
||||||
}
|
|
||||||
if (field.getType().isAssignableFrom(newClazz) && remoteTransport != null) {
|
|
||||||
field.set(rs, createRemoteService(name, executor, serviceClass, clientAddress, groups, remoteTransport));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Resource res = field.getAnnotation(Resource.class);
|
|
||||||
if (res == null) continue;
|
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
if (res.name().equals(RESNAME_SNCP_GROUPS)) {
|
if (remoteTransport == null) {
|
||||||
if (groups == null) groups = new LinkedHashSet<>();
|
List<Transport> list = new ArrayList<>();
|
||||||
if (groupArray == null) groupArray = groups.toArray(new String[groups.size()]);
|
if (sameGroupTransport != null) list.add(sameGroupTransport);
|
||||||
if (field.getGenericType().equals(GROUPS_TYPE1)) {
|
if (diffGroupTransports != null) list.addAll(diffGroupTransports);
|
||||||
field.set(rs, groups);
|
if (!list.isEmpty()) remoteTransport = new Transport(list);
|
||||||
} else if (field.getGenericType().equals(GROUPS_TYPE2)) {
|
|
||||||
field.set(rs, groupArray);
|
|
||||||
}
|
|
||||||
} else if (res.name().endsWith(RESNAME_SNCP_ADDR)) {
|
|
||||||
if (field.getType() == String.class) {
|
|
||||||
field.set(rs, clientAddress == null ? null : (clientAddress.getHostString() + ":" + clientAddress.getPort()));
|
|
||||||
} else {
|
|
||||||
field.set(rs, clientAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (remoteService == null && remoteTransport != null) {
|
||||||
|
remoteService = createRemoteService(name, executor, serviceClass, clientAddress, remoteTransport);
|
||||||
|
}
|
||||||
|
if (remoteService != null) field.set(rs, remoteService);
|
||||||
}
|
}
|
||||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||||
}
|
}
|
||||||
@@ -724,7 +715,7 @@ public abstract class Sncp {
|
|||||||
try {
|
try {
|
||||||
Field e = newClazz.getDeclaredField("_client");
|
Field e = newClazz.getDeclaredField("_client");
|
||||||
e.setAccessible(true);
|
e.setAccessible(true);
|
||||||
client = new SncpClient(name, executor, hash(serviceClass), false, newClazz, clientAddress, groups);
|
client = new SncpClient(name, executor, hash(serviceClass), false, newClazz, clientAddress);
|
||||||
e.set(rs, client);
|
e.set(rs, client);
|
||||||
} catch (NoSuchFieldException ne) {
|
} catch (NoSuchFieldException ne) {
|
||||||
}
|
}
|
||||||
@@ -735,19 +726,23 @@ public abstract class Sncp {
|
|||||||
if (client != null) {
|
if (client != null) {
|
||||||
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
||||||
sb.append(", action.size = ").append(client.getActionCount());
|
sb.append(", action.size = ").append(client.getActionCount());
|
||||||
|
List<String> groups = new ArrayList<>();
|
||||||
|
if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
|
||||||
|
if (diffGroupTransports != null) {
|
||||||
|
for (Transport t : diffGroupTransports) {
|
||||||
|
groups.add(t.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
|
sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
|
||||||
List<InetSocketAddress> addrs = new ArrayList<>();
|
sb.append(", sameaddrs = ").append(sameGroupTransport == null ? null : Arrays.asList(sameGroupTransport.getRemoteAddresses()));
|
||||||
for (Transport t : sameGroupTransports) {
|
|
||||||
addrs.addAll(Arrays.asList(t.getRemoteAddress()));
|
|
||||||
}
|
|
||||||
sb.append(", samegroups = ").append(addrs);
|
|
||||||
|
|
||||||
addrs.clear();
|
List<InetSocketAddress> addrs = new ArrayList<>();
|
||||||
for (Transport t : diffGroupTransports) {
|
if (diffGroupTransports != null) {
|
||||||
addrs.addAll(Arrays.asList(t.getRemoteAddress()));
|
for (Transport t : diffGroupTransports) {
|
||||||
|
addrs.addAll(Arrays.asList(t.getRemoteAddresses()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sb.append(", diffgroups = ").append(addrs);
|
sb.append(", diffaddrs = ").append(addrs);
|
||||||
} else {
|
} else {
|
||||||
sb.append(", ").append(MultiRun.class.getSimpleName().toLowerCase()).append(" = false");
|
sb.append(", ").append(MultiRun.class.getSimpleName().toLowerCase()).append(" = false");
|
||||||
}
|
}
|
||||||
@@ -758,11 +753,11 @@ public abstract class Sncp {
|
|||||||
}
|
}
|
||||||
if (client == null) return rs;
|
if (client == null) return rs;
|
||||||
{
|
{
|
||||||
Field c = newClazz.getDeclaredField("_sameGroupTransports");
|
Field c = newClazz.getDeclaredField("_sameGroupTransport");
|
||||||
c.setAccessible(true);
|
c.setAccessible(true);
|
||||||
c.set(rs, sameGroupTransports.toArray(new Transport[sameGroupTransports.size()]));
|
c.set(rs, sameGroupTransport);
|
||||||
}
|
}
|
||||||
{
|
if (diffGroupTransports != null) {
|
||||||
Field t = newClazz.getDeclaredField("_diffGroupTransports");
|
Field t = newClazz.getDeclaredField("_diffGroupTransports");
|
||||||
t.setAccessible(true);
|
t.setAccessible(true);
|
||||||
t.set(rs, diffGroupTransports.toArray(new Transport[diffGroupTransports.size()]));
|
t.set(rs, diffGroupTransports.toArray(new Transport[diffGroupTransports.size()]));
|
||||||
@@ -780,6 +775,7 @@ public abstract class Sncp {
|
|||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
* @Resource(name = "")
|
* @Resource(name = "")
|
||||||
* @SncpDyn(remote = true)
|
* @SncpDyn(remote = true)
|
||||||
|
* @ResourceType({TestService.class})
|
||||||
* public final class _DynRemoteTestService extends TestService{
|
* public final class _DynRemoteTestService extends TestService{
|
||||||
*
|
*
|
||||||
* @Resource
|
* @Resource
|
||||||
@@ -837,7 +833,7 @@ public abstract class Sncp {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass,
|
public static <T extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass,
|
||||||
final InetSocketAddress clientAddress, HashSet<String> groups, final Transport transport) {
|
final InetSocketAddress clientAddress, final Transport transport) {
|
||||||
if (serviceClass == null) return null;
|
if (serviceClass == null) return null;
|
||||||
if (!Service.class.isAssignableFrom(serviceClass)) return null;
|
if (!Service.class.isAssignableFrom(serviceClass)) return null;
|
||||||
int mod = serviceClass.getModifiers();
|
int mod = serviceClass.getModifiers();
|
||||||
@@ -852,7 +848,7 @@ public abstract class Sncp {
|
|||||||
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
||||||
ClassLoader loader = Sncp.class.getClassLoader();
|
ClassLoader loader = Sncp.class.getClassLoader();
|
||||||
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName();
|
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName();
|
||||||
final SncpClient client = new SncpClient(name, executor, hash(serviceClass), true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress, groups);
|
final SncpClient client = new SncpClient(name, executor, hash(serviceClass), true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
|
||||||
try {
|
try {
|
||||||
Class newClazz = Class.forName(newDynName.replace('/', '.'));
|
Class newClazz = Class.forName(newDynName.replace('/', '.'));
|
||||||
T rs = (T) newClazz.newInstance();
|
T rs = (T) newClazz.newInstance();
|
||||||
@@ -867,8 +863,8 @@ public abstract class Sncp {
|
|||||||
sb.append(newClazz.getName()).append("{name = ").append(name);
|
sb.append(newClazz.getName()).append("{name = ").append(name);
|
||||||
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
||||||
sb.append(", action.size = ").append(client.getActionCount());
|
sb.append(", action.size = ").append(client.getActionCount());
|
||||||
sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
|
sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName());
|
||||||
sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddress()));
|
sb.append(", remoteaddrs = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses()));
|
||||||
sb.append("}");
|
sb.append("}");
|
||||||
Field s = newClazz.getDeclaredField("_selfstring");
|
Field s = newClazz.getDeclaredField("_selfstring");
|
||||||
s.setAccessible(true);
|
s.setAccessible(true);
|
||||||
@@ -889,6 +885,22 @@ public abstract class Sncp {
|
|||||||
av0.visit("name", name);
|
av0.visit("name", name);
|
||||||
av0.visitEnd();
|
av0.visitEnd();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
|
||||||
|
{
|
||||||
|
AnnotationVisitor av1 = av0.visitArray("value");
|
||||||
|
ResourceType rty = serviceClass.getAnnotation(ResourceType.class);
|
||||||
|
if (rty == null) {
|
||||||
|
av1.visit(null, Type.getType(Type.getDescriptor(serviceClass)));
|
||||||
|
} else {
|
||||||
|
for (Class cl : rty.value()) {
|
||||||
|
av1.visit(null, Type.getType(Type.getDescriptor(cl)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
}
|
||||||
|
av0.visitEnd();
|
||||||
|
}
|
||||||
{
|
{
|
||||||
av0 = cw.visitAnnotation(sncpDynDesc, true);
|
av0 = cw.visitAnnotation(sncpDynDesc, true);
|
||||||
av0.visit("remote", Boolean.TRUE);
|
av0.visit("remote", Boolean.TRUE);
|
||||||
@@ -1070,8 +1082,8 @@ public abstract class Sncp {
|
|||||||
sb.append(newClazz.getName()).append("{name = ").append(name);
|
sb.append(newClazz.getName()).append("{name = ").append(name);
|
||||||
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid());
|
||||||
sb.append(", action.size = ").append(client.getActionCount());
|
sb.append(", action.size = ").append(client.getActionCount());
|
||||||
sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups);
|
sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName());
|
||||||
sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddress()));
|
sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses()));
|
||||||
sb.append("}");
|
sb.append("}");
|
||||||
Field s = newClazz.getDeclaredField("_selfstring");
|
Field s = newClazz.getDeclaredField("_selfstring");
|
||||||
s.setAccessible(true);
|
s.setAccessible(true);
|
||||||
|
|||||||
@@ -129,8 +129,6 @@ public final class SncpClient {
|
|||||||
|
|
||||||
protected final InetSocketAddress address;
|
protected final InetSocketAddress address;
|
||||||
|
|
||||||
protected final HashSet<String> groups;
|
|
||||||
|
|
||||||
private final byte[] addrBytes;
|
private final byte[] addrBytes;
|
||||||
|
|
||||||
private final int addrPort;
|
private final int addrPort;
|
||||||
@@ -144,12 +142,11 @@ public final class SncpClient {
|
|||||||
protected final Consumer<Runnable> executor;
|
protected final Consumer<Runnable> executor;
|
||||||
|
|
||||||
public SncpClient(final String serviceName, final Consumer<Runnable> executor, final DLong serviceid, boolean remote, final Class serviceClass,
|
public SncpClient(final String serviceName, final Consumer<Runnable> executor, final DLong serviceid, boolean remote, final Class serviceClass,
|
||||||
final InetSocketAddress clientAddress, final HashSet<String> groups) {
|
final InetSocketAddress clientAddress) {
|
||||||
this.remote = remote;
|
this.remote = remote;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.serviceClass = serviceClass;
|
this.serviceClass = serviceClass;
|
||||||
this.address = clientAddress;
|
this.address = clientAddress;
|
||||||
this.groups = groups;
|
|
||||||
//if (subLocalClass != null && !serviceClass.isAssignableFrom(subLocalClass)) throw new RuntimeException(subLocalClass + " is not " + serviceClass + " sub class ");
|
//if (subLocalClass != null && !serviceClass.isAssignableFrom(subLocalClass)) throw new RuntimeException(subLocalClass + " is not " + serviceClass + " sub class ");
|
||||||
this.name = serviceName;
|
this.name = serviceName;
|
||||||
this.nameid = Sncp.hash(serviceName);
|
this.nameid = Sncp.hash(serviceName);
|
||||||
@@ -187,7 +184,7 @@ public final class SncpClient {
|
|||||||
if (remote) service = service.replace(Sncp.LOCALPREFIX, Sncp.REMOTEPREFIX);
|
if (remote) service = service.replace(Sncp.LOCALPREFIX, Sncp.REMOTEPREFIX);
|
||||||
return this.getClass().getSimpleName() + "(service = " + service + ", serviceid = " + serviceid + ", nameid = " + nameid
|
return this.getClass().getSimpleName() + "(service = " + service + ", serviceid = " + serviceid + ", nameid = " + nameid
|
||||||
+ ", name = '" + name + "', address = " + (address == null ? "" : (address.getHostString() + ":" + address.getPort()))
|
+ ", name = '" + name + "', address = " + (address == null ? "" : (address.getHostString() + ":" + address.getPort()))
|
||||||
+ ", groups = " + groups + ", actions.size = " + actions.length + ")";
|
+ ", actions.size = " + actions.length + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Method> parseMethod(final Class serviceClass) {
|
public static List<Method> parseMethod(final Class serviceClass) {
|
||||||
@@ -230,11 +227,50 @@ public final class SncpClient {
|
|||||||
return multis;
|
return multis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remoteSameGroup(final BsonConvert convert, Transport transport, final int index, final Object... params) {
|
||||||
|
final SncpAction action = actions[index];
|
||||||
|
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null; //不能让远程调用handler,因为之前本地方法已经调用过了
|
||||||
|
for (InetSocketAddress addr : transport.getRemoteAddresses()) {
|
||||||
|
remote0(null, convert, transport, addr, action, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void asyncRemoteSameGroup(final BsonConvert convert, Transport transport, final int index, final Object... params) {
|
||||||
|
if (executor != null) {
|
||||||
|
executor.accept(() -> {
|
||||||
|
remoteSameGroup(convert, transport, index, params);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
remoteSameGroup(convert, transport, index, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remoteDiffGroup(final BsonConvert convert, Transport[] transports, final int index, final Object... params) {
|
||||||
|
if (transports == null || transports.length < 1) return;
|
||||||
|
final SncpAction action = actions[index];
|
||||||
|
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null; //不能让远程调用handler,因为之前本地方法已经调用过了
|
||||||
|
for (Transport transport : transports) {
|
||||||
|
remote0(null, convert, transport, null, action, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void asyncRemoteDiffGroup(final BsonConvert convert, Transport[] transports, final int index, final Object... params) {
|
||||||
|
if (transports == null || transports.length < 1) return;
|
||||||
|
if (executor != null) {
|
||||||
|
executor.accept(() -> {
|
||||||
|
remoteDiffGroup(convert, transports, index, params);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
remoteDiffGroup(convert, transports, index, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//只给远程模式调用的
|
||||||
public <T> T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) {
|
public <T> T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) {
|
||||||
final SncpAction action = actions[index];
|
final SncpAction action = actions[index];
|
||||||
final CompletionHandler handlerFunc = action.handlerFuncParamIndex >= 0 ? (CompletionHandler) params[action.handlerFuncParamIndex] : null;
|
final CompletionHandler handlerFunc = action.handlerFuncParamIndex >= 0 ? (CompletionHandler) params[action.handlerFuncParamIndex] : null;
|
||||||
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null;
|
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null;
|
||||||
Future<byte[]> future = remote0(handlerFunc, convert, transport, action, params);
|
Future<byte[]> future = remote0(handlerFunc, convert, transport, null, action, params);
|
||||||
if (handlerFunc != null) return null;
|
if (handlerFunc != null) return null;
|
||||||
final BsonReader reader = convert.pollBsonReader();
|
final BsonReader reader = convert.pollBsonReader();
|
||||||
try {
|
try {
|
||||||
@@ -257,22 +293,11 @@ public final class SncpClient {
|
|||||||
if (transports == null || transports.length < 1) return;
|
if (transports == null || transports.length < 1) return;
|
||||||
remote(convert, transports[0], index, params);
|
remote(convert, transports[0], index, params);
|
||||||
for (int i = 1; i < transports.length; i++) {
|
for (int i = 1; i < transports.length; i++) {
|
||||||
remote0(null, convert, transports[i], actions[index], params);
|
remote0(null, convert, transports[i], null, actions[index], params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void asyncRemote(final BsonConvert convert, Transport[] transports, final int index, final Object... params) {
|
private Future<byte[]> remote0(final CompletionHandler handler, final BsonConvert convert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
|
||||||
if (transports == null || transports.length < 1) return;
|
|
||||||
if (executor != null) {
|
|
||||||
executor.accept(() -> {
|
|
||||||
remote(convert, transports, index, params);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
remote(convert, transports, index, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Future<byte[]> remote0(final CompletionHandler handler, final BsonConvert convert, final Transport transport, final SncpAction action, final Object... params) {
|
|
||||||
Type[] myparamtypes = action.paramTypes;
|
Type[] myparamtypes = action.paramTypes;
|
||||||
if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.address;
|
if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.address;
|
||||||
final BsonWriter writer = convert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入
|
final BsonWriter writer = convert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入
|
||||||
@@ -283,7 +308,7 @@ public final class SncpClient {
|
|||||||
final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度
|
final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度
|
||||||
final long seqid = System.nanoTime();
|
final long seqid = System.nanoTime();
|
||||||
final DLong actionid = action.actionid;
|
final DLong actionid = action.actionid;
|
||||||
final SocketAddress addr = action.addressTargetParamIndex >= 0 ? (SocketAddress) params[action.addressTargetParamIndex] : null;
|
final SocketAddress addr = addr0 == null ? (action.addressTargetParamIndex >= 0 ? (SocketAddress) params[action.addressTargetParamIndex] : null) : addr0;
|
||||||
final AsyncConnection conn = transport.pollConnection(addr);
|
final AsyncConnection conn = transport.pollConnection(addr);
|
||||||
if (conn == null || !conn.isOpen()) {
|
if (conn == null || !conn.isOpen()) {
|
||||||
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") cannot connect " + (conn == null ? addr : conn.getRemoteAddress()));
|
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") cannot connect " + (conn == null ? addr : conn.getRemoteAddress()));
|
||||||
|
|||||||
@@ -154,9 +154,9 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
*
|
*
|
||||||
* @Override
|
* @Override
|
||||||
* public void action(final BsonReader in, final BsonWriter out) throws Throwable {
|
* public void action(final BsonReader in, final BsonWriter out) throws Throwable {
|
||||||
* TestBean arg1 = convert.convertFrom(in, paramTypes[1]);
|
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
|
||||||
* String arg2 = convert.convertFrom(in, paramTypes[2]);
|
* String arg2 = convert.convertFrom(paramTypes[2], in);
|
||||||
* int arg3 = convert.convertFrom(in, paramTypes[3]);
|
* int arg3 = convert.convertFrom(paramTypes[3], in);
|
||||||
* Object rs = service.change(arg1, arg2, arg3);
|
* Object rs = service.change(arg1, arg2, arg3);
|
||||||
* callParameter(out, arg1, arg2, arg3);
|
* callParameter(out, arg1, arg2, arg3);
|
||||||
* convert.convertTo(out, paramTypes[0], rs);
|
* convert.convertTo(out, paramTypes[0], rs);
|
||||||
@@ -210,9 +210,9 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
mv.visitMaxs(1, 1);
|
mv.visitMaxs(1, 1);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
String convertFromDesc = "(" + convertReaderDesc + "Ljava/lang/reflect/Type;)Ljava/lang/Object;";
|
String convertFromDesc = "(Ljava/lang/reflect/Type;" + convertReaderDesc + ")Ljava/lang/Object;";
|
||||||
try {
|
try {
|
||||||
convertFromDesc = Type.getMethodDescriptor(BsonConvert.class.getMethod("convertFrom", BsonReader.class, java.lang.reflect.Type.class));
|
convertFromDesc = Type.getMethodDescriptor(BsonConvert.class.getMethod("convertFrom", java.lang.reflect.Type.class, BsonReader.class));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
throw new RuntimeException(ex); //不可能会发生
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,6 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
for (int i = 0; i < paramClasses.length; i++) { //参数
|
for (int i = 0; i < paramClasses.length; i++) { //参数
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class));
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
|
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
|
||||||
if (iconst > ICONST_5) {
|
if (iconst > ICONST_5) {
|
||||||
@@ -236,6 +235,7 @@ public final class SncpDynServlet extends SncpServlet {
|
|||||||
mv.visitInsn(iconst); //
|
mv.visitInsn(iconst); //
|
||||||
}
|
}
|
||||||
mv.visitInsn(AALOAD);
|
mv.visitInsn(AALOAD);
|
||||||
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
|
||||||
int load = ALOAD;
|
int load = ALOAD;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public final class SncpServer extends Server {
|
|||||||
final int port = this.address.getPort();
|
final int port = this.address.getPort();
|
||||||
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.creatCounter");
|
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.creatCounter");
|
||||||
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.cycleCounter");
|
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.cycleCounter");
|
||||||
final int rcapacity = Math.max(this.capacity, 4 * 1024);
|
final int rcapacity = Math.max(this.bufferCapacity, 4 * 1024);
|
||||||
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
|
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
|
||||||
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
|
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
|
||||||
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
|
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.redkale.util.*;
|
|||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@AutoLoad(false)
|
@AutoLoad(false)
|
||||||
|
@ResourceType({CacheSourceService.class, CacheSource.class})
|
||||||
public class CacheSourceService<K extends Serializable, V extends Object> implements CacheSource<K, V>, Service, AutoCloseable {
|
public class CacheSourceService<K extends Serializable, V extends Object> implements CacheSource<K, V>, Service, AutoCloseable {
|
||||||
|
|
||||||
@Resource(name = "APP_HOME")
|
@Resource(name = "APP_HOME")
|
||||||
|
|||||||
@@ -12,10 +12,13 @@ import org.redkale.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@AutoLoad(false)
|
@AutoLoad(false)
|
||||||
|
@ResourceType({DataCacheListenerService.class, DataCacheListener.class})
|
||||||
public class DataCacheListenerService implements DataCacheListener, Service {
|
public class DataCacheListenerService implements DataCacheListener, Service {
|
||||||
|
|
||||||
@Resource(name = "$")
|
@Resource(name = "$")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂时不实现
|
* 暂时不实现
|
||||||
@@ -25,6 +26,7 @@ import javax.annotation.Resource;
|
|||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@AutoLoad(false)
|
@AutoLoad(false)
|
||||||
|
@ResourceType({DataSQLListenerService.class, DataSQLListener.class})
|
||||||
public class DataSQLListenerService implements DataSQLListener, Service {
|
public class DataSQLListenerService implements DataSQLListener, Service {
|
||||||
|
|
||||||
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
|
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ import org.redkale.util.*;
|
|||||||
/**
|
/**
|
||||||
* DataSource对应的Service类, 该类主要特点是将所有含FilterBean参数的方法重载成FilterNode对应的方法。
|
* DataSource对应的Service类, 该类主要特点是将所有含FilterBean参数的方法重载成FilterNode对应的方法。
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@AutoLoad(false)
|
@AutoLoad(false)
|
||||||
|
@ResourceType({DataSourceService.class, DataSource.class})
|
||||||
public class DataSourceService implements DataSource, Service, AutoCloseable {
|
public class DataSourceService implements DataSource, Service, AutoCloseable {
|
||||||
|
|
||||||
@Resource(name = "$")
|
@Resource(name = "$")
|
||||||
|
|||||||
@@ -8,9 +8,16 @@ package org.redkale.service;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有Service的实现类不得声明为final, 允许远程模式的public方法和public String name()方法都不能声明为final。
|
* 所有Service的实现类不得声明为final, 允许远程模式的public方法都不能声明为final。
|
||||||
* 注意: "$"是一个很特殊的Service.name值 。 被标记为@Resource(name = "$") 的Service的资源名与所属父Service的资源名一致。
|
* 注意: "$"是一个很特殊的Service.name值 。 被标记为@Resource(name = "$") 的Service的资源名与所属父Service的资源名一致。
|
||||||
*
|
* <p>
|
||||||
|
* <blockquote><pre>
|
||||||
|
* Service的资源类型
|
||||||
|
* 业务逻辑的Service通常有两种编写方式:
|
||||||
|
* 1、只写一个Service实现类。
|
||||||
|
* 2、先定义业务的Service接口或抽象类,再编写具体实现类。
|
||||||
|
* 第二种方式需要在具体实现类上使用@ResourceType指明资源注入的类型。
|
||||||
|
* </pre></blockquote>
|
||||||
* <p>
|
* <p>
|
||||||
* @Resource(name = ".*")
|
* @Resource(name = ".*")
|
||||||
* private HashMap<String, XXXService> nodemap;
|
* private HashMap<String, XXXService> nodemap;
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.service;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <blockquote><pre>
|
|
||||||
* Service的资源类型
|
|
||||||
* 业务逻辑的Service通常有两种编写方式:
|
|
||||||
* 1、只写一个Service实现类。
|
|
||||||
* 2、先定义业务的Service接口或抽象类,再编写具体实现类。
|
|
||||||
* @ServiceResource用于第二种方式, 在具体实现类上需要使用@ServiceResource指明资源注入的类型。
|
|
||||||
* </pre></blockquote>
|
|
||||||
* <p>
|
|
||||||
* 详情见: http://www.redkale.org
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({TYPE})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface ServiceResource {
|
|
||||||
|
|
||||||
Class<? extends Service> value();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -14,10 +14,13 @@ import org.redkale.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://www.redkale.org
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@AutoLoad(false)
|
@AutoLoad(false)
|
||||||
|
@ResourceType({WebSocketNodeService.class, WebSocketNode.class})
|
||||||
public class WebSocketNodeService extends WebSocketNode implements Service {
|
public class WebSocketNodeService extends WebSocketNode implements Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -67,7 +67,15 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void register(final String name, final Object rs) {
|
public void register(final String name, final Object rs) {
|
||||||
register(name, rs.getClass(), rs);
|
final Class claz = rs.getClass();
|
||||||
|
ResourceType rtype = (ResourceType) claz.getAnnotation(ResourceType.class);
|
||||||
|
if (rtype == null) {
|
||||||
|
register(name, claz, rs);
|
||||||
|
} else {
|
||||||
|
for (Class cl : rtype.value()) {
|
||||||
|
register(name, cl, rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <A> void register(final String name, final Class<? extends A> clazz, final A rs) {
|
public <A> void register(final String name, final Class<? extends A> clazz, final A rs) {
|
||||||
|
|||||||
26
src/org/redkale/util/ResourceType.java
Normal file
26
src/org/redkale/util/ResourceType.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显式的指明资源类型
|
||||||
|
* <p>
|
||||||
|
* 详情见: http://www.redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
@Target({TYPE})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface ResourceType {
|
||||||
|
|
||||||
|
Class[] value();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user