`
chenkangxian
  • 浏览: 87625 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

一个简单的rpc框架的实现

阅读更多

 

为了降低开发成本,提升已有系统的利用率,企业往往会构建自己的SOA体系结构,SOA构建的手段有多种,可以通过webservicerestfulrmisocket等等,笔者通过java socket,来构建一个简单的SOA体系结构,以下代码仅供参考。

 

 

1.  需要实现SOA的服务接口

 

package com.chenkangxian.rpc.impl;

/**
 *
 * @Author: chenkangxian
 *
 * @Annotation: 根据key取数据接口
 *
 * @Date:2012-5-13
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 *
 */

public interface DataService {

    String getData(String key);

}

 

2.   接口的实现

 

 

package com.chenkangxian.rpc.impl;

/**
 *
 * @Author: chenkangxian
 *
 * @Annotation: 根据key取数据服务实现
 *
 * @Date:2012-5-13
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 *
 */
public class DataServiceImpl implements DataService {

	public String getData(String key) {
		
        return "this is the data when key = " + key ;
    }

}
 

 

3.  执行代理

 

 

/**
 * 
 */
package com.chenkangxian.rpc.impl;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.Socket;

/**
 * @Author: chenkangxian
 *
 * @Annotation: 执行代理
 *
 * @Date:2012-5-15
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 * 
 */
public class InvocationProxy implements InvocationHandler{

	private String host;
	private int port;

	public InvocationProxy(String host, int port){
		this.host = host;
		this.port = port;
	}

	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();
		}
	}
}

 

4.    服务消费者

 

 

package com.chenkangxian.rpc.impl;

/**
 * @Author: chenkangxian
 *
 * @Annotation: 服务消费者
 *
 * @Date:2012-5-13
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 *
 */
public class RpcConsumer {
    
    public static void main(String[] args) throws Exception {
        DataService service = RpcFramework.refer(DataService.class, "127.0.0.1", 1234);
        for (int i = 0; i < Integer.MAX_VALUE; i ++) {
            String value = service.getData("key_" + i);
            System.out.println(value);
            Thread.sleep(1000);
        }
    }
    
}

 

5.    远程调用框架

 

 

package com.chenkangxian.rpc.impl;

import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *
 * @Author: chenkangxian
 *
 * @Annotation: 简单的远程调用框架实现
 *
 * @Date:2012-5-13
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 *
 */
public class RpcFramework {
	
	/**
	 * 暴露服务
	 * 
	 * Author: chenkangxian
	 *
	 * Last Modification Time: 2012-5-15
	 *
	 * @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();
				ThreadPoolHelp.getExecutorInstance().execute(new WorkThread(service, socket));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 引用服务
	 * 
	 * Author: chenkangxian
	 *
	 * Last Modification Time: 2012-5-15
	 *
	 * @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 InvocationProxy(host,port));
	}

}

 

 

6.    服务提供者

 

 

package com.chenkangxian.rpc.impl;

/**
 * @Author: chenkangxian
 *
 * @Annotation: 服务提供者
 *
 * @Date:2012-5-13
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 *
 */
public class RpcProvider {

    public static void main(String[] args) throws Exception {
        DataService service = new DataServiceImpl();
        RpcFramework.export(service, 1234);
    }

}

 

7.    线程池帮助类

 

 

/**
 * 
 */
package com.chenkangxian.rpc.impl;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: chenkangxian
 *
 * @Annotation:  线程池帮助类
 *
 * @Date:2012-5-15
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 * 
 */
public class ThreadPoolHelp {

	private static ExecutorService executor ;
	
	static{
		executor = Executors.newFixedThreadPool(20);
	}
	
	public static ExecutorService getExecutorInstance(){
		return executor;
	}
}

 

 

8.    工作线程

 

 

/**
 * 
 */
package com.chenkangxian.rpc.impl;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

/**
 *
 * @Author: chenkangxian
 *
 * @Annotation: 工作线程
 *
 * @Date:2012-5-15
 *
 * @Copyright: 2012 chenkangxian, All rights reserved.
 * 
 */
public class WorkThread implements Runnable {
	
	private Object service;
	
	private Socket socket;
	
	public WorkThread(Object service,Socket socket){
		this.service = service;
		this.socket = socket;
	}

    @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();
        }
    }

}
 

 

 

 

分享到:
评论
2 楼 lizhi8888 2015-12-15  
lizhi8888 写道
你好,我按你写的书中第一章的rpc实现,写了几个类,发现在provider在反序列话的时候,提示:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Class; cannot be cast to java.lang.Class
at rpc.Provider.main(Provider.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

我觉得是是classloader不同导致的,但是用该博文提供的rpc实现确实可以运行的。这到底是为什么?


已经解决,是我写错了,Class [] 强制转换成 Class导致的
1 楼 lizhi8888 2015-12-15  
你好,我按你写的书中第一章的rpc实现,写了几个类,发现在provider在反序列话的时候,提示:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Class; cannot be cast to java.lang.Class
at rpc.Provider.main(Provider.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

我觉得是是classloader不同导致的,但是用该博文提供的rpc实现确实可以运行的。这到底是为什么?

相关推荐

    实现一个简单的RPC框架

    以上就是使用socket、反射和序列化技术实现简单RPC框架的主要过程。这个框架虽然基础,但已经能够展示RPC的核心思想。对于更复杂的场景,如负载均衡、服务发现、容错机制等,可以在此基础上进行扩展和完善。在实际...

    如何实现一个简单的RPC框架

    实现一个简单的RPC框架主要涉及以下几个关键点: 1. **网络通信库**:Netty是一个高性能、异步事件驱动的网络应用框架,常用于构建高并发、低延迟的服务器。在RPC框架中,Netty可以处理客户端与服务端之间的网络...

    JAVA实现简单RPC框架

    在这个“JAVA实现简单RPC框架”的项目中,我们将探讨如何利用Java的核心特性来构建这样的框架。以下是关键知识点的详细说明: 1. **JDK动态代理**: JDK动态代理是Java提供的一种机制,可以在运行时创建一个实现了...

    Netty4.1实战-手写RPC框架.pdf

    本专题主要通过三个章节实现一个rpc通信的基础功能,来学习RPC服务中间件是如何开发和使用。章节内以源码加说明实战方式来讲解,请尽可能下载源码学习。 - 手写RPC框架第一章《自定义配置xml》 - 手写RPC框架第二章...

    Java rpc框架简易版,类似dubbo分布式实现 (纯socket实现).zip

    本项目提供了一个简易版的Java RPC框架实现,旨在模仿著名的Dubbo框架,但采用了更基础的Socket通信方式进行分布式服务的搭建。以下是这个项目的核心知识点: 1. **RPC原理**:RPC使得客户端可以像调用本地方法一样...

    自己写了一个RPC框架

    在这个场景中,你提到的是你自己编写了一个RPC框架,这是一项技术挑战,因为RPC框架涉及到网络通信、序列化、服务注册与发现等多个关键领域。 在你提供的博客链接中...

    RPC框架的实现原理,及RPC架构组件详解.pdf

    详细讲解RPC

    一款基于Netty+Zookeeper+Spring实现的轻量级Java RPC框架。提供服务注册,发现,负载均衡,.zip

    通过Zookeeper,RPC框架可以实现简单的负载均衡策略,如轮询、随机等。当有多个服务提供者时,消费者可以从Zookeeper获取到所有可用的服务实例,然后根据负载均衡策略选择一个合适的实例进行调用,这样可以有效分摊...

    最简单的JAVA RPC框架实现

    在"最简单的JAVA RPC框架实现"这个项目中,你将学习如何构建一个基本的RPC系统,包括服务接口定义、序列化处理、网络通信的实现、服务的注册与发现等。虽然它可能不包含高级特性,如负载均衡、服务治理等,但对于...

    可参考的自定义实现rpc框架

    标题中的“可参考的自定义实现rpc框架”指的是一个关于如何设计和实现远程过程调用(RPC)框架的教程或示例项目。RPC允许不同计算机系统间的程序进行通信,仿佛它们是在同一台机器上直接调用函数一样。下面将详细...

    基于 Spark Netty Rpc 框架,重新实现的一个 Netty Rpc 框架 ( scala + java ).zip

    标题中的“基于 Spark Netty Rpc 框架,重新实现的一个 Netty Rpc 框架 ( scala + java )”指的是一个开发项目,该项目利用了Apache Spark的Netty RPC(远程过程调用)机制,并以此为基础创建了一个新的RPC框架。...

    基于Java实现一个简易的RPC框架【100012743】

    在这个基于Java实现的简易RPC框架项目中,我们将深入探讨如何构建这样一个框架,并实现对`printf`函数的远程调用。 首先,我们要理解RPC的基本原理。RPC使得客户端可以像调用本地方法一样调用远程服务器上的方法,...

    基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip

    基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现...

    基于akka与scala实现一个简单rpc框架【100010261】

    详情介绍:https://www.yuque.com/sxbn/ks/100010261 基于akka与scala实现一个简单rpc框架 RPC,即 Remote Procedure Call(远程过程调用)。

    jsonrpc是一个基于Java的高性能开源RPC框架

    在Java世界中,JSON-RPC作为一个高性能的开源RPC框架,为分布式系统中的服务调用提供了便利。这个框架允许应用程序通过网络在不同的进程之间传递方法调用,仿佛这些方法是在本地对象上调用一样。 JSON-RPC的核心...

    JAVA RPC框架简单开发实现

    本文将深入探讨如何基于Java实现一个简单的RPC框架,并涉及心跳检测和生产消费者模型这两个关键概念。 首先,RPC允许一个程序调用另一个在不同地址空间中的程序,这个地址空间可能在同一个机器上,也可能在远程网络...

    基于netty的手写rpc框架

    在本项目中,我们将基于Netty实现一个手写的RPC框架。Netty是Java领域的一个高性能、异步事件驱动的网络应用程序框架,常用于构建高效的服务器和客户端。 首先,我们需要理解RPC框架的基本组成部分: 1. **服务...

    Hadoop自己的Rpc框架使用Demo

    本教程将通过一个简单的Demo来讲解如何在自己的项目中利用Hadoop的RPC框架。 首先,理解RPC的基本概念是非常必要的。RPC允许一个程序调用另一个远程程序,就像调用本地函数一样,无需关心远程调用的细节。Hadoop的...

    RPC框架底层模拟

    RPC(Remote Procedure Call)框架是分布式系统中广泛使用的通信机制,它允许一个程序在不关心远程服务器具体实现的情况下调用其方法,就像调用本地对象一样。本篇将深入探讨RPC框架的底层模拟,主要围绕以下几个...

Global site tag (gtag.js) - Google Analytics