java实现RPC

一,服务提供者

工程为battercake-provider,项目结构图如下图所示

1.1 先创建一个“卖煎饼”微服务的接口和实现类

package com.jp.service;

public interface BatterCakeService {
    /**
     * 卖煎饼的服务
     */
    public String sellBatterCake(String name);
}
package com.jp.service;

import com.jp.service.BatterCakeService;

/**
 * 卖煎饼服务的实现类
 *
 */
public class BatterCakeServiceImpl implements BatterCakeService {

    public String sellBatterCake(String name) {
        return name+"煎饼,卖的特别好";
    }
}

1.2 RPC框架调用部分

该部分有两个关键部分:RPC服务提供器线程处理类

1)RPC服务提供器

  1. 需要发布的服务存储在一个内存变量serviceList中。(该例就是把卖煎饼服务的实例对象传入
  2. 启动socket,server.accept()方法阻塞在那,监听输入
  3. 针对每一个请求,单独启动一个线程处理
 1 package com.jp.rpc;
 2
 3 import java.net.ServerSocket;
 4 import java.net.Socket;
 5 import java.util.ArrayList;
 6 import java.util.Arrays;
 7 import java.util.List;
 8 /**
 9  * RPC服务提供器
10  * 1,将需要发布的服务存储在一个内存变量serviceList中
11  * 2,启动socket,server.accept()方法阻塞在那,监听输入
12  * 3,针对每一个请求,单独启动一个线程处理
13  */
14 public class RpcProvider {
15
16     //存储注册的服务列表
17     private static List<Object> serviceList;
18
19     /**
20      * 发布rpc服务
21      * @param object 提供(卖煎饼)服务的实例对象
22      * @param port 监听的端口
23      * @throws Exception
24      */
25     public static void export(int port,Object... services) throws Exception {
26         serviceList=Arrays.asList(services);
27         ServerSocket server = new ServerSocket(port);
28         Socket client = null;
29         while (true) {
30             //阻塞等待输入,每来一个请求就会产生一个socket对象
31             client = server.accept();
32             //每一个请求,启动一个线程处理
33             new Thread(new ServerThread(client,serviceList)).start();
34         }
35     }
36 }

2)线程处理类

ServerThread(socke对象服务实例列表)线程处理类的代码,ServerThread主要做以下几个步骤

  1. 读取客户端发送的服务名
  2. 判断服务是否发布
  3. 如果发布,则走反射逻辑,动态调用,返回结果
  4. 如果未发布,则返回提示通知
 1 package com.jp.rpc;
 2
 3 import java.io.IOException;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 import java.lang.reflect.Method;
 7 import java.net.Socket;
 8 import java.util.List;
 9
10 public class ServerThread implements Runnable {
11
12     private Socket client = null;
13
14     private List<Object> serviceList = null;
15
16     public ServerThread(Socket client, List<Object> service) {
17         this.client = client;
18         this.serviceList = service;
19     }
20
21     //@Override
22     public void run() {
23         ObjectInputStream input = null;
24         ObjectOutputStream output = null;
25         try {
26             input = new ObjectInputStream(client.getInputStream());
27             output = new ObjectOutputStream(client.getOutputStream());
28             // 读取客户端要访问那个service
29             Class serviceClass = (Class) input.readObject();
30             // 找到该服务类实例
31             Object obj = findService(serviceClass);
32             if (obj == null) {
33                 output.writeObject(serviceClass.getName() + "服务未发现");
34             } else {
35                 //利用反射调用该方法,返回结果
36                 //从请求中得到请求的方法名和方法参数;加上上面得到了服务对象实例;反射得到具体的方法实例;invoke执行
37                 try {
38                     String methodName = input.readUTF();
39                     Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
40                     Object[] arguments = (Object[]) input.readObject();
41
42                     Method method = obj.getClass().getMethod(methodName, parameterTypes);
43                     Object result = method.invoke(obj, arguments);
44                     output.writeObject(result);
45                 } catch (Throwable t) {
46                     output.writeObject(t);
47                 }
48             }
49         } catch (Exception e) {
50             e.printStackTrace();
51         } finally {
52             try {
53                 client.close();
54                 input.close();
55                 output.close();
56             } catch (IOException e) {
57                 // TODO Auto-generated catch block
58                 e.printStackTrace();
59             }
60         }
61
62     }
63
64     //到服务列表中找服务实例
65     private Object findService(Class serviceClass) {
66         for (Object obj : serviceList) {
67             boolean isFather = serviceClass.isAssignableFrom(obj.getClass());
68             if (isFather) {
69                 return obj;
70             }
71         }
72         return null;
73     }
74
75 }

1.3 发布服务

 1 package com.jp.start;
 2
 3 import com.jp.rpc.RpcProvider;
 4 import com.jp.service.BatterCakeService;
 5 import com.jp.service.BatterCakeServiceImpl;
 6
 7 public class RpcBootStrap {
 8     public static void main(String[] args) throws Exception {
 9         //实例化“卖煎饼”这个服务的实现类
10         BatterCakeService batterCakeService =new BatterCakeServiceImpl();
11         //发布卖煎饼的服务:注册在20006端口,并把提供服务的实例传入
12         RpcProvider.export(20006,batterCakeService);
13     }
14 }

二,服务消费者

消费者工程为battercake-consumer,项目结构图如下图所示

2.1 rpc调用部分

分为两部分:代理类处理器(代理类工厂)和 service的代理类对象(即前面工厂生产返回的)

1)代理类处理器(代理类工厂)

负责生产代理类(传入服务的名字(类?);ip;端口

 1 package com.jp.rpc;
 2
 3 import java.lang.reflect.Proxy;
 4
 5 /**
 6  * 用于生产服务代理类
 7  */
 8 public class RpcConsumer {
 9     public static <T> T getService(Class<T> clazz,String ip,int port) {
10         ProxyHandler proxyHandler =new ProxyHandler(ip,port);
11         return (T)Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class<?>[] {clazz}, proxyHandler);
12     }
13 }

2)服务代理类的处理器(该类就是代理类功能的具体实现者,其实就是封装了调用远程服务的过程(封装请求数据发给远端服务提供者,把提供者返回的结果返回)

  1. 建立socket连接
  2. 封装请求数据,发送给服务提供者
  3. 返回结果
 1 package com.jp.rpc;
 2
 3 import java.io.ObjectInputStream;
 4 import java.io.ObjectOutputStream;
 5 import java.lang.reflect.InvocationHandler;
 6 import java.lang.reflect.Method;
 7 import java.net.Socket;
 8
 9 public class ProxyHandler implements InvocationHandler {
10
11     private String ip;
12     private int port;
13
14     public ProxyHandler(String ip, int port) {
15         this.ip = ip;
16         this.port = port;
17     }
18
19     //@Override
20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21         Socket socket = new Socket(this.ip, this.port);
22         ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
23         ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
24         try {
25             output.writeObject(proxy.getClass().getInterfaces()[0]);
26             output.writeUTF(method.getName());
27             output.writeObject(method.getParameterTypes());
28             output.writeObject(args);
29             output.flush();
30             Object result = input.readObject();
31             if (result instanceof Throwable) {
32                 throw (Throwable) result;
33             }
34             return result;
35         } finally {
36             socket.shutdownOutput();
37         }
38     }
39
40 }

2.2 接下来建立一个测试类RpcTest如下

(跑该测试类前,记得运行在battercake-provider端的RpcBootstrap类发布BatterCakeService服务)

 1 package com.jp.start;
 2
 3 import com.jp.rpc.RpcConsumer;
 4 import com.jp.service.BatterCakeService;
 5
 6 public class RpcTest {
 7     public static void main(String[] args) {
 8         //生成代理类,三个参数:被代理对象,ip,端口
 9         BatterCakeService batterCakeService = RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006);
10         //调用代理类的方法并获得结果
11         String result = batterCakeService.sellBatterCake("双蛋");
12         System.out.println(result);
13     }
14 }

输出结果如下

https://blog.csdn.net/wangyunpeng0319/article/details/78651998

https://www.cnblogs.com/rjzheng/category/1205773.html

原文地址:https://www.cnblogs.com/xdyixia/p/9227738.html

时间: 2024-10-08 15:34:22

java实现RPC的相关文章

基于Netty的高性能JAVA的RPC框架

前言 今年7月份左右报名参加了阿里巴巴组织的高性能中间件挑战赛,这次比赛不像以往的比赛,是从一个工程的视角来比赛的. 这个比赛有两个赛题,第一题是实现一个RPC框架,第二道题是实现一个Mom消息中间件. RPC题目如下 一个简单的RPC框架 RPC(Remote Procedure Call )--远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据.在OSI网络通信模型中,RPC

利用jmeter+JAVA对RPC的单接口(dubbo接口等)进行性能测试

建立JAVA项目 建立maven项目,加入Jmeter所需要的JAR包依赖. POM.xml  加入如下: <dependency> <groupId>org.apache.jmeter</groupId> <artifactId>ApacheJMeter_core</artifactId> <version>3.2</version> </dependency> <!-- https://mvnrepo

java之rpc/orm

Netty线程模型 其中ChannelPiepline的设计模型采用的是Handler组成的责任链模型 blocking I/O 阻塞nonblocking I/O 非阻塞I/O multiplexing (select and poll) 多路复用signal driven I/O (SIGIO) 信号驱动asynchronous I/O (the POSIX aio_functions) 异步 例子: 假设某银行只有10个职员.该银行的业务流程分为以下4个步骤: 1) 顾客填申请表(5分钟)

Java实现简单的RPC框架

一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).Hessian.Http invoker等.另外,RPC是与语言无关的. RPC示意图 如上图所示,假设Computer1在调用sayHi()方法,对于Computer1而言调用sayHi()方法就像调用本地方法一样,调用 –>返回.但从后续调用可以看出Computer1调用的是Computer2

java RPC系列之二 HTTPINVOKER

java RPC系列之二  HTTPINVOKER 一.java RPC简单的汇总 java的RPC得到技术,基本包含以下几个,分别是:RMI(远程方法调用) .Caucho的Hessian 和 Burlap .Spring的基于HTTP的远程服务.以及使用JAX-RPC和JAX-WS的Web服务.本文主要介绍spring的httpinvoker的基本的配置实现. 二.Spring的httpinvoker的配置实现 基本步骤:       1.定义好服务端需要提供的接口方法(客户端调用的接口):

Java RMI与RPC的区别

转载自:https://www.cnblogs.com/ygj0930/p/6542811.html:加了一些自己的理解: 一:RPC 远程过程调用(注:可以这么理解,RPC是所有语言的通用协议,有点像SOAP,而RMI是RPC的一种Java实现『或说RMI是RPC的java版的细化要求』:这是自己目前的理解如果有不正确的地方还望能指出) RPC(Remote Procedure Call Protocol)远程过程调用协议,通过网络从远程计算机上请求调用某种服务.(注:可以这么理解,只要是通过

RPC框架性能基本比较测试

gRPC是Google最近公布的开源软件,基于最新的HTTP2.0协议,并支持常见的众多编程语言. 我们知道HTTP2.0是基于二进制的HTTP协议升级版本,目前各大浏览器都在快马加鞭的加以支持. 我们可以设想一下,未来浏览器支持HTTP2.0,并通过现有开源序列化库比如protobuf等,可以直接和各种语言的服务进行高效交互,这将是多么“美好”的场景! gPRC的Java实现底层网络库是Netty,而且是用到最新的Netty5.0.0.Alpha3的开发版本,因为最新版本针对HTTP/2做了很

为什么需要RPC,而不是简单的HTTP接口

转载自:http://www.oschina.net/question/271044_2155059?sort=default&p=1#answers 目前有很多Java的RPC框架,有基于Json的,有基于XML,也有基于二进制对象的. 论复杂度,RPC框架肯定是高于简单的HTTP接口的.但毋庸置疑,HTTP接口由于受限于HTTP协议,需要带HTTP请求头,导致传输起来效率或者说安全性不如RPC. 现在问题是,遇到怎样的瓶颈了才需要或者说更适合用RPC(比如像阿里这么大的请求并发量,简单的HT

venus java高并发框架

http://www.iteye.com/topic/1118484 因为有 netty.mima等远程框架.包括spring jboss等remoting框架 和阿里的dubbo相比, 没有亮点... dubbo都要出2.0.9了. 监控系统界面都出来了..重要是dubbo是SOA的思想, 而且提供了很多自治的一些功能. 还在阿里内部大范围使用(久经考验, 最近的阿里社区网站也是用dubbo做的)(http://code.alibabatech.com/wiki/display/dubbo/H