A small framework for asynchronous Rpc calls based on Netty

A small framework for asynchronous Rpc calls based on netty, welcome to shoot bricks, novice.

 

Client-server communication class

package cc.ymsoft.Framework;

import java.io.Serializable;

@SuppressWarnings("serial")
public class MethodAndArgs implements Serializable{
	private String methodName;//Name of the method called
	private Class<?>[] types;//Parameter types
	private Object[] objects;//Parameter list
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	public Class<?>[] getTypes() {
		return types;
	}
	public void setTypes(Class<?>[] types) {
		this.types = types;
	}
	public Object[] getObjects() {
		return objects;
	}
	public void setObjects(Object[] objects) {
		this.objects = objects;
	}
	public MethodAndArgs() {
		super();
		// TODO Auto-generated constructor stub
	}
	public MethodAndArgs(String methodName, Class<?>[] types, Object[] objects) {
		
		this.methodName = methodName;
		this.types = types;
		this.objects = objects;
	}
	
	
}

 

 Framework class, there are two static methods, regist (register the service on the server) and getobjt (the proxy class to get the interface)

/**
 * @author xulang
 */
package cc.ymsoft.Framework;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
/**
 * Server processing
 * @author hadoop
 *
 */
 class TcpServerHandler extends ChannelInboundHandlerAdapter {
    
    private Object obj;
    private Object response;
    
    public TcpServerHandler(Object obj) {
		super();
		this.obj = obj;
		
	}
	@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        // TODO Auto-generated method stub
		MethodAndArgs methodAndArgs=(MethodAndArgs) msg;
		Method method=obj.getClass().getMethod(methodAndArgs.getMethodName(), methodAndArgs.getTypes());
		ctx.writeAndFlush(method.invoke(obj, methodAndArgs.getObjects()));
        ctx.close();
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    	// TODO Auto-generated method stub
    	System.out.println("client die");
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("channelActive>>>>>>>>");
        ctx.writeAndFlush("call exception");
        ctx.close();
    }
      @Override
   public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("Server exception");
    }
}
/**
 * Client processing
 * @author hadoop
 *
 */
 class TcpClientHander extends ChannelInboundHandlerAdapter {
	 private Object response;
	 
		public Object getResponse() {
		return response;
	}

		@Override
	    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
			response=msg;
	        System.out.println("client received a message from the server: " + msg);
	    }
	    
		@Override
	    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
	        System.out.println("client exception is general");
	    }
	}
 
public class RpcFramework {

	/**
	 * Service registration
	 * @param obj the service object that needs to be registered
	 * @param port port
	 * @param ip address
	 * @throws InterruptedException
	 */
	public static void regist(final Object obj,int port,String ip) throws InterruptedException {
		int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors()*2;
		    
		int BIZTHREADSIZE = 100;
		 EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE);
		  EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE);
		if (obj == null)
			throw new IllegalArgumentException("Object cannot be null");
		if (port <= 0 || port > 65535)
			throw new IllegalArgumentException("wrong port" + port);
		 ServerBootstrap bootstrap = new ServerBootstrap();
	        bootstrap.group(bossGroup, workerGroup);
	        bootstrap.channel(NioServerSocketChannel.class);
	        bootstrap.childHandler(new ChannelInitializer<Channel>() {

	            @Override
	            protected void initChannel(Channel ch) throws Exception {
	                // TODO Auto-generated method stub
	                ChannelPipeline pipeline = ch.pipeline();
	                 pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
	                    pipeline.addLast(new LengthFieldPrepender(4));
	                    pipeline.addLast("encoder", new ObjectEncoder());  
	                    pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
	                  //  pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
	                   // pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
	                    pipeline.addLast(new TcpServerHandler(obj));
	            }       
	        });
	          ChannelFuture f = bootstrap.bind(ip, port).sync();
	          f.channel().closeFuture().sync();
	          System.out.println("TCP server started");
	}
	@SuppressWarnings("unchecked")
	public static <T>T getObj(Class<T> interfaceClass,final String host,final int port) {
		if (interfaceClass == null)
			throw new IllegalArgumentException("Interface type cannot be null");
		if (!interfaceClass.isInterface())
			throw new IllegalArgumentException("class name" + interfaceClass.getName() + "must be an interface");
		if (host == null || host.length() == 0)
			throw new IllegalArgumentException("The target host cannot be empty");
		if (port <= 0 || port > 65535)
			throw new IllegalArgumentException("Port error: " + port);
		
	return (T)	Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				
				MethodAndArgs mArgs=new MethodAndArgs(method.getName(), method.getParameterTypes(), args);
				 final TcpClientHander tcpClientHander=new TcpClientHander();
				  EventLoopGroup group = new NioEventLoopGroup();
		          try {
		              Bootstrap b = new Bootstrap();
		              b.group(group);
		         //     b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true);
		              b.channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true);
		             
		              b.handler(new ChannelInitializer<SocketChannel>() {
		                  @Override
		                  protected void initChannel(SocketChannel ch) throws Exception {
		                      ChannelPipeline pipeline = ch.pipeline();
		                      pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
		                      pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
		                      pipeline.addLast("encoder", new ObjectEncoder());  
		                      pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
		                      pipeline.addLast("handler",tcpClientHander);
		                  }
		              });
		              
		                   ChannelFuture f = b.connect(host, port).sync();    
		                
		                  f.channel().writeAndFlush(mArgs).sync();
		                   f.channel().closeFuture().sync();
		                 
		          } catch (Exception e) {

		          } finally {
		        	  
		              group.shutdownGracefully();
		          }
				return tcpClientHander.getResponse();
		     
				
			}
		});
	}
}

  test

interface

package cc.ymsoft.test;

interface HelloService {
	String SayHello(String name);
}

 interface implementation class

package cc.ymsoft.test;

public class HelloImp implements HelloService {

	@Override
	public String SayHello(String name) {
		// TODO Auto-generated method stub
		
		return "Hello:"+name;
	}


}

 client

package cc.ymsoft.test;

import cc.ymsoft.Framework.RpcFramework;

public class HelloInvoke {
	
	public static void main(String[] args) throws Exception {
		final HelloService helloService = RpcFramework.getObj(HelloService.class, "127.0.0.1", 1717);
	
		
					System.out.println(helloService.SayHello("XL"));
				
		
	}

}

 Server

 

package cc.ymsoft.test;

import cc.ymsoft.Framework.RpcFramework;

public class HelloPro {
	public static void main(String[] args) throws Exception {
		HelloService hello=new HelloImp();
		RpcFramework.regist(hello, 1717, "127.0.0.1");
	}
	
}

 

The complete code is on github https://github.com/xulang/NettyRpc

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326609824&siteId=291194637