RPC框架几行代码就够了

摘自梁飞的博客 - RPC框架几行代码就够了

简易RPC框架实现:
/* 
 * Copyright 2011 Alibaba.com All right reserved. This software is the 
 * confidential and proprietary information of Alibaba.com ("Confidential 
 * Information"). You shall not disclose such Confidential Information and shall 
 * use it only in accordance with the terms of the license agreement you entered 
 * into with Alibaba.com. 
 */  
package com.alibaba.study.rpc.framework;  
  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
import java.net.ServerSocket;  
import java.net.Socket;  
  
/** 
 * RpcFramework 
 *  
 * @author william.liangf 
 */  
public class RpcFramework {  
  
    /** 
     * 暴露服务 
     *  
     * @param service 服务实现 
     * @param port 服务端口 
     * @throws Exception 
     */  
    public static void export(final Object service, int port) throws Exception {  
        if (service == null)  
            throw new IllegalArgumentException("service instance == null");  
        if (port <= 0 || port > 65535)  
            throw new IllegalArgumentException("Invalid port " + port);  
        System.out.println("Export service " + service.getClass().getName() + " on port " + port);  
        ServerSocket server = new ServerSocket(port);  
        for(;;) {  
            try {  
                final Socket socket = server.accept();  
                new Thread(new Runnable() {  
                    @Override  
                    public void run() {  
                        try {  
                            try {  
                                ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
                                try {  
                                    String methodName = input.readUTF();  
                                    Class<?>[] parameterTypes = (Class<?>[])input.readObject();  
                                    Object[] arguments = (Object[])input.readObject();  
                                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());  
                                    try {  
                                        Method method = service.getClass().getMethod(methodName, parameterTypes);  
                                        Object result = method.invoke(service, arguments);  
                                        output.writeObject(result);  
                                    } catch (Throwable t) {  
                                        output.writeObject(t);  
                                    } finally {  
                                        output.close();  
                                    }  
                                } finally {  
                                    input.close();  
                                }  
                            } finally {  
                                socket.close();  
                            }  
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                    }  
                }).start();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 引用服务 
     *  
     * @param <T> 接口泛型 
     * @param interfaceClass 接口类型 
     * @param host 服务器主机名 
     * @param port 服务器端口 
     * @return 远程服务 
     * @throws Exception 
     */  
    @SuppressWarnings("unchecked")  
    public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {  
        if (interfaceClass == null)  
            throw new IllegalArgumentException("Interface class == null");  
        if (! interfaceClass.isInterface())  
            throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");  
        if (host == null || host.length() == 0)  
            throw new IllegalArgumentException("Host == null!");  
        if (port <= 0 || port > 65535)  
            throw new IllegalArgumentException("Invalid port " + port);  
        System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);  
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {  
            public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {  
                Socket socket = new Socket(host, port);  
                try {  
                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());  
                    try {  
                        output.writeUTF(method.getName());  
                        output.writeObject(method.getParameterTypes());  
                        output.writeObject(arguments);  
                        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
                        try {  
                            Object result = input.readObject();  
                            if (result instanceof Throwable) {  
                                throw (Throwable) result;  
                            }  
                            return result;  
                        } finally {  
                            input.close();  
                        }  
                    } finally {  
                        output.close();  
                    }  
                } finally {  
                    socket.close();  
                }  
            }  
        });  
    }  
  
}  
使用示例:
1.定义服务接口
/* 
 * Copyright 2011 Alibaba.com All right reserved. This software is the 
 * confidential and proprietary information of Alibaba.com ("Confidential 
 * Information"). You shall not disclose such Confidential Information and shall 
 * use it only in accordance with the terms of the license agreement you entered 
 * into with Alibaba.com. 
 */  
package com.alibaba.study.rpc.test;  
  
/** 
 * HelloService 
 *  
 * @author william.liangf 
 */  
public interface HelloService {  
  
    String hello(String name);  
  
} 
2.实现服务
/* 
 * Copyright 2011 Alibaba.com All right reserved. This software is the 
 * confidential and proprietary information of Alibaba.com ("Confidential 
 * Information"). You shall not disclose such Confidential Information and shall 
 * use it only in accordance with the terms of the license agreement you entered 
 * into with Alibaba.com. 
 */  
package com.alibaba.study.rpc.test;  
  
/** 
 * HelloServiceImpl 
 *  
 * @author william.liangf 
 */  
public class HelloServiceImpl implements HelloService {  
  
    public String hello(String name) {  
        return "Hello " + name;  
    }  
  
}  
3.暴露服务
/* 
 * Copyright 2011 Alibaba.com All right reserved. This software is the 
 * confidential and proprietary information of Alibaba.com ("Confidential 
 * Information"). You shall not disclose such Confidential Information and shall 
 * use it only in accordance with the terms of the license agreement you entered 
 * into with Alibaba.com. 
 */  
package com.alibaba.study.rpc.test;  
  
import com.alibaba.study.rpc.framework.RpcFramework;  
  
/** 
 * RpcProvider 
 *  
 * @author william.liangf 
 */  
public class RpcProvider {  
  
    public static void main(String[] args) throws Exception {  
        HelloService service = new HelloServiceImpl();  
        RpcFramework.export(service, 1234);  
    }  
  
}  
4.引用服务
/* 
 * Copyright 2011 Alibaba.com All right reserved. This software is the 
 * confidential and proprietary information of Alibaba.com ("Confidential 
 * Information"). You shall not disclose such Confidential Information and shall 
 * use it only in accordance with the terms of the license agreement you entered 
 * into with Alibaba.com. 
 */  
package com.alibaba.study.rpc.test;  
  
import com.alibaba.study.rpc.framework.RpcFramework;  
  
/** 
 * RpcConsumer 
 *  
 * @author william.liangf 
 */  
public class RpcConsumer {  
      
    public static void main(String[] args) throws Exception {  
        HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);  
        for (int i = 0; i < Integer.MAX_VALUE; i ++) {  
            String hello = service.hello("World" + i);  
            System.out.println(hello);  
            Thread.sleep(1000);  
        }  
    }  
      
}  

转载于:https://my.oschina.net/amhuman/blog/2251576

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Java RPC Netty 框架代码实现: ```java // 定义 RPC 请求实体类 public class RpcRequest implements Serializable { private String className; private String methodName; private Object[] parameters; // 省略 getter 和 setter 方法 } // 定义 RPC 响应实体类 public class RpcResponse implements Serializable { private Object result; private String error; // 省略 getter 和 setter 方法 } // 定义 RPC 服务接口 public interface RpcService { // 定义服务方法 public int add(int a, int b); } // 实现 RPC 服务接口 public class RpcServiceImpl implements RpcService { @Override public int add(int a, int b) { return a + b; } } // 定义 RPC 服务器端 public class RpcServer { private static final Logger LOGGER = LoggerFactory.getLogger(RpcServer.class); private String host; private int port; public RpcServer(String host, int port) { this.host = host; this.port = port; } public void start() throws InterruptedException { // 创建线程池 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // 配置服务器启动类 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 添加解码器和编码器 ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null))); ch.pipeline().addLast(new ObjectEncoder()); // 添加业务处理类 ch.pipeline().addLast(new RpcServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 启动服务器 ChannelFuture f = b.bind(host, port).sync(); LOGGER.info("Server started on {}:{}", host, port); // 等待直到服务器 socket 关闭 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } // 定义业务处理类 private class RpcServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { RpcRequest request = (RpcRequest) msg; LOGGER.info("Received request: {}", request); // 调用服务 RpcResponse response = new RpcResponse(); try { Class<?> clazz = Class.forName(request.getClassName()); Method method = clazz.getMethod(request.getMethodName(), request.getParameters().getClass()); Object result = method.invoke(clazz.newInstance(), request.getParameters()); LOGGER.info("Result: {}", result); response.setResult(result); } catch (Exception e) { LOGGER.error("Error occurred while invoking service: {}", e.getMessage()); response.setError(e.getMessage()); } // 返回响应 ctx.writeAndFlush(response); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { LOGGER.error("Error occurred in server: {}", cause.getMessage()); ctx.close(); } } } // 定义 RPC 客户端 public class RpcClient { private static final Logger LOGGER = LoggerFactory.getLogger(RpcClient.class); private String host; private int port; public RpcClient(String host, int port) { this.host = host; this.port = port; } public Object invoke(String className, String methodName, Object... parameters) { // 创建连接 EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 添加解码器和编码器 ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null))); ch.pipeline().addLast(new ObjectEncoder()); // 添加业务处理类 ch.pipeline().addLast(new RpcClientHandler()); } }) .option(ChannelOption.SO_KEEPALIVE, true); // 连接服务器 ChannelFuture f = b.connect(host, port).sync(); LOGGER.info("Connected to server {}:{}", host, port); // 发送请求 RpcRequest request = new RpcRequest(); request.setClassName(className); request.setMethodName(methodName); request.setParameters(parameters); f.channel().writeAndFlush(request); // 等待服务器响应 RpcResponse response = RpcClientHandler.getResponse(); if (response.getError() != null) { LOGGER.error("Error occurred while invoking service: {}", response.getError()); } else { LOGGER.info("Result: {}", response.getResult()); return response.getResult(); } // 关闭连接 f.channel().closeFuture().sync(); } catch (Exception e) { LOGGER.error("Error occurred in client: {}", e.getMessage()); } finally { group.shutdownGracefully(); } return null; } // 定义业务处理类 private static class RpcClientHandler extends ChannelInboundHandlerAdapter { private static RpcResponse response; public static RpcResponse getResponse() { return response; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { response = (RpcResponse) msg; LOGGER.info("Received response: {}", response); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { LOGGER.error("Error occurred in client: {}", cause.getMessage()); ctx.close(); } } } // 测试代码 public class RpcTest { public static void main(String[] args) throws InterruptedException { // 启动服务器 RpcServer server = new RpcServer("localhost", 8080); server.start(); // 等待服务器启动 Thread.sleep(1000); // 创建客户端并调用服务 RpcClient client = new RpcClient("localhost", 8080); RpcService service = (RpcService) client.invoke("RpcServiceImpl", "add", 1, 2); System.out.println(service.add(1, 2)); } } ``` 以上代码实现了一个简单的 Java RPC Netty 框架,包括 RPC 请求和响应实体类、RPC 服务接口和实现类、RPC 服务器端和客户端。其中,RPC 服务器端和客户端都使用了 Netty 框架,通过序列化和反序列化实现了数据的传输和处理。在测试代码中,我们启动了一个 RPC 服务器,并通过客户端调用了 RPC 服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值