mirror of https://github.com/longtai-cn/hippo4j
fix : Add set multiple ChannelHandler(#812)
parent
6a88b2bd0a
commit
fbb6d05dee
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.rpc.handler;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage the Handler used in the processing.<br>
|
||||||
|
* The Handler must be able to exist multiple times and be invoked once in a single execution
|
||||||
|
*/
|
||||||
|
public interface HandlerManager<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add handler to the end of the Handler chain
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param handler handler
|
||||||
|
*/
|
||||||
|
HandlerManager<T> addLast(String name, T handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add handler to the head of the Handler chain
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param handler handler
|
||||||
|
*/
|
||||||
|
HandlerManager<T> addFirst(String name, T handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add handler to the end of the Handler chain, without specifying a name
|
||||||
|
*
|
||||||
|
* @param handler handler
|
||||||
|
*/
|
||||||
|
HandlerManager<T> addLast(T handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds handler to the head of the Handler chain, without specifying a name
|
||||||
|
*
|
||||||
|
* @param handler handler
|
||||||
|
*/
|
||||||
|
HandlerManager<T> addFirst(T handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a handler
|
||||||
|
*
|
||||||
|
* @param order order
|
||||||
|
* @param handler Handler
|
||||||
|
* @param name Handler name
|
||||||
|
* @return HandlerEntity
|
||||||
|
*/
|
||||||
|
default HandlerEntity<T> getHandlerEntity(long order, T handler, String name) {
|
||||||
|
return new HandlerEntity<>(order, handler, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
class HandlerEntity<T> implements Comparable<HandlerEntity<T>>{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* order, The Handler with a larger value is executed after the Handler with a smaller value
|
||||||
|
*/
|
||||||
|
long order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handler
|
||||||
|
*/
|
||||||
|
T handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A high level summary of handler functionality
|
||||||
|
*/
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(HandlerEntity<T> o) {
|
||||||
|
return (int) (this.getOrder() - o.getOrder());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.rpc.handler;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.toolkit.Assert;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor manager for ChannelHandler in netty
|
||||||
|
*/
|
||||||
|
public abstract class NettyHandlerManager implements HandlerManager<ChannelHandler> {
|
||||||
|
|
||||||
|
protected final List<HandlerEntity<ChannelHandler>> handlers;
|
||||||
|
|
||||||
|
AtomicLong firstIndex = new AtomicLong(-1);
|
||||||
|
|
||||||
|
AtomicLong lastIndex = new AtomicLong(0);
|
||||||
|
|
||||||
|
protected NettyHandlerManager(List<ChannelHandler> handlers) {
|
||||||
|
this.handlers = handlers.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(c -> getHandlerEntity(lastIndex.getAndIncrement(), c, null))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NettyHandlerManager(ChannelHandler... handlers) {
|
||||||
|
this(handlers != null ? Arrays.asList(handlers) : Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NettyHandlerManager() {
|
||||||
|
this.handlers = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param handler handler
|
||||||
|
* @return NettyHandlerManager
|
||||||
|
*/
|
||||||
|
public NettyHandlerManager addLast(String name, ChannelHandler handler) {
|
||||||
|
Assert.notNull(handler);
|
||||||
|
this.handlers.add(getHandlerEntity(lastIndex.getAndIncrement(), handler, name));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @param name name
|
||||||
|
* @param handler handler
|
||||||
|
* @return NettyHandlerManager
|
||||||
|
*/
|
||||||
|
public NettyHandlerManager addFirst(String name, ChannelHandler handler) {
|
||||||
|
Assert.notNull(handler);
|
||||||
|
this.handlers.add(getHandlerEntity(firstIndex.getAndIncrement(), handler, name));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @param handler handler
|
||||||
|
* @return NettyHandlerManager
|
||||||
|
*/
|
||||||
|
public NettyHandlerManager addLast(ChannelHandler handler) {
|
||||||
|
Assert.notNull(handler);
|
||||||
|
this.handlers.add(getHandlerEntity(lastIndex.getAndIncrement(), handler, null));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @param handler handler
|
||||||
|
* @return NettyHandlerManager
|
||||||
|
*/
|
||||||
|
public NettyHandlerManager addFirst(ChannelHandler handler) {
|
||||||
|
Assert.notNull(handler);
|
||||||
|
this.handlers.add(getHandlerEntity(firstIndex.getAndDecrement(), handler, null));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.rpc.client;
|
||||||
|
|
||||||
|
import cn.hippo4j.rpc.handler.NettyClientPoolHandler;
|
||||||
|
import cn.hippo4j.rpc.handler.NettyClientTakeHandler;
|
||||||
|
import cn.hippo4j.rpc.handler.NettyServerTakeHandler;
|
||||||
|
import cn.hippo4j.rpc.request.DefaultRequest;
|
||||||
|
import cn.hippo4j.rpc.request.Request;
|
||||||
|
import cn.hippo4j.rpc.response.Response;
|
||||||
|
import cn.hippo4j.rpc.server.NettyServerConnection;
|
||||||
|
import cn.hippo4j.rpc.server.RPCServer;
|
||||||
|
import cn.hippo4j.rpc.server.ServerConnection;
|
||||||
|
import cn.hippo4j.rpc.support.ClassRegistry;
|
||||||
|
import cn.hippo4j.rpc.support.DefaultInstance;
|
||||||
|
import cn.hippo4j.rpc.support.Instance;
|
||||||
|
import io.netty.channel.pool.ChannelPoolHandler;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class RPCClientTest {
|
||||||
|
|
||||||
|
String host = "localhost";
|
||||||
|
int port = 8888;
|
||||||
|
int portTest = 8889;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connection() throws IOException {
|
||||||
|
Class<CallManager> cls = CallManager.class;
|
||||||
|
String className = cls.getName();
|
||||||
|
ClassRegistry.put(className, cls);
|
||||||
|
// The mode connection was denied when the server was started on the specified port
|
||||||
|
Instance instance = new DefaultInstance();
|
||||||
|
NettyServerTakeHandler handler = new NettyServerTakeHandler(instance);
|
||||||
|
ServerConnection connection = new NettyServerConnection(handler);
|
||||||
|
RPCServer rpcServer = new RPCServer(port, connection);
|
||||||
|
CompletableFuture.runAsync(rpcServer::bind);
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(3);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
ChannelPoolHandler channelPoolHandler = new NettyClientPoolHandler(new NettyClientTakeHandler());
|
||||||
|
NettyClientConnection clientConnection = new NettyClientConnection(host, port, channelPoolHandler);
|
||||||
|
RPCClient rpcClient = new RPCClient(clientConnection);
|
||||||
|
Request request = new DefaultRequest("127.0.0.18888", className, "call", null, null);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
Response response = rpcClient.connection(request);
|
||||||
|
boolean active = rpcClient.isActive();
|
||||||
|
Assert.assertTrue(active);
|
||||||
|
Assert.assertEquals(response.getObj(), 1);
|
||||||
|
}
|
||||||
|
rpcClient.close();
|
||||||
|
rpcServer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test case can be overridden under the handler and coder packages
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void connectionTest() throws IOException {
|
||||||
|
Class<CallManager> cls = CallManager.class;
|
||||||
|
String className = cls.getName();
|
||||||
|
ClassRegistry.put(className, cls);
|
||||||
|
// The mode connection was denied when the server was started on the specified port
|
||||||
|
Instance instance = new DefaultInstance();
|
||||||
|
NettyServerTakeHandler handler = new NettyServerTakeHandler(instance);
|
||||||
|
ServerConnection connection = new NettyServerConnection(handler);
|
||||||
|
RPCServer rpcServer = new RPCServer(portTest, connection);
|
||||||
|
CompletableFuture.runAsync(rpcServer::bind);
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(3);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
ChannelPoolHandler channelPoolHandler = new NettyClientPoolHandler(new NettyClientTakeHandler());
|
||||||
|
NettyClientConnection clientConnection = new NettyClientConnection(host, portTest, channelPoolHandler);
|
||||||
|
RPCClient rpcClient = new RPCClient(clientConnection);
|
||||||
|
Class<?>[] classes = new Class<?>[2];
|
||||||
|
classes[0] = Integer.class;
|
||||||
|
classes[1] = Integer.class;
|
||||||
|
Object[] objects = new Object[2];
|
||||||
|
objects[0] = 1;
|
||||||
|
objects[1] = 2;
|
||||||
|
Request request = new DefaultRequest("127.0.0.18889", className, "callTest", classes, objects);
|
||||||
|
Response response = rpcClient.connection(request);
|
||||||
|
boolean active = rpcClient.isActive();
|
||||||
|
Assert.assertTrue(active);
|
||||||
|
Assert.assertEquals(response.getObj(), 3);
|
||||||
|
rpcClient.close();
|
||||||
|
rpcServer.close();
|
||||||
|
}
|
||||||
|
}
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cn.hippo4j.config.rpc.client;
|
|
||||||
|
|
||||||
import cn.hippo4j.config.rpc.request.DefaultRequest;
|
|
||||||
import cn.hippo4j.config.rpc.request.Request;
|
|
||||||
import cn.hippo4j.config.rpc.response.Response;
|
|
||||||
import cn.hippo4j.config.rpc.server.NettyServerConnection;
|
|
||||||
import cn.hippo4j.config.rpc.server.RPCServer;
|
|
||||||
import cn.hippo4j.config.rpc.server.ServerConnection;
|
|
||||||
import cn.hippo4j.config.rpc.support.DefaultInstance;
|
|
||||||
import cn.hippo4j.config.rpc.support.Instance;
|
|
||||||
import cn.hippo4j.config.rpc.support.ClassRegistry;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class RPCClientTest {
|
|
||||||
|
|
||||||
String host = "localhost";
|
|
||||||
int port = 8888;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void connection() throws IOException {
|
|
||||||
|
|
||||||
Class<CallManager> cls = CallManager.class;
|
|
||||||
String className = cls.getName();
|
|
||||||
ClassRegistry.put(className, cls);
|
|
||||||
// The mode connection was denied when the server was started on the specified port
|
|
||||||
Instance instance = new DefaultInstance();
|
|
||||||
ServerConnection connection = new NettyServerConnection(instance);
|
|
||||||
RPCServer rpcServer = new RPCServer(port, connection);
|
|
||||||
CompletableFuture.runAsync(rpcServer::bind);
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(3);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
NettyClientConnection clientConnection = new NettyClientConnection(host, port);
|
|
||||||
RPCClient rpcClient = new RPCClient(clientConnection);
|
|
||||||
Request request = new DefaultRequest("127.0.0.18888", className, "call", null, null);
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
Response response = rpcClient.connection(request);
|
|
||||||
Assert.assertEquals(response.getObj(), 1);
|
|
||||||
}
|
|
||||||
rpcClient.close();
|
|
||||||
rpcServer.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in new issue