基于JAVA的RPC简单实现

基于JAVA的RPC简单实现。

一、RPC是什么?

        RPC即Remote Procedure Call 是一种进程间通信方式。RPC是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议,是分布式系统常见的一种通信方法。RPC采用客户机/服务器模式。

二、RPC框架结构图

基于JAVA的RPC简单实现_第1张图片

 

二、RPC框架流程图

基于JAVA的RPC简单实现_第2张图片

四、代码实现

    1.rpc-framework(父项目)

pom.xml文件,引入依赖。


    4.0.0
    com.wc
    rpcProject-framework
    pom
    1.0.0-SNAPSHOT
    
        rpc-common
        rpc-proto
        rpc-codec
        rpc-transport
        rpc-server
        rpc-client
        rpc-example
    
    
    
        4.13
        1.18.8
        1.7.26
        1.2.3
        2.5
        9.4.28.v20200408
        1.2.62
        1.8
    
    
    
        
        
            junit
            junit
            ${junit.version}
            test
        
        
        
            org.projectlombok
            lombok
            ${lombok.version}
        
        
        
            org.slf4j
                slf4j-api
            ${slf4j-api.version}
        
        
            ch.qos.logback
            logback-classic
            ${logback-classic.version}
        
    
    
    
        
            
            
                com.alibaba
                dubbo
                2.5.4
            
            
            
                common-io
                commons-io
                2.5
              
            
            
            
                org.eclipose.jetty
                jetty-servlet
                ${jetty-servlet.version}
            
            
            
                com.alibaba
                fastjson
                ${fastjson.version}
            

        

    

    
    
        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.0
                
                    ${java.version} 
                    ${java.version} 
                    UTF-8
                
            
        
    

    2.rpc-common(公共模块)

ReflectionUtils(反射工具类)

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

/**
 * 反射工具类
 */
@Slf4j
public class ReflectionUtils {
    /**
     * 根据传入的Class创建相应的对象
     * @param clazz 待创建对象的类
     * @param  对象类型
     * @return 创建的对象
     */
    public static  T newInstance(Class clazz) throws Exception{
        try{
            return clazz.newInstance();
        }catch (Exception e){
            log.error(e.getMessage(),e);
            throw new IllegalStateException(e);
        }
    }

    /**
     * 获取传入类自有的公共方法
     * @param clazz  传入类
     * @return 传入类自有的公共方法
     * @throws Exception
     */
    public static Method[] getPublicMethods(Class clazz)throws Exception{
        try{
            //调用getMethods方法输出的是自身的public方法和父类Object的public方法
            //调用getDeclaredMethods方法输出的是自身的public、protected、private方法
            Method[] methods=clazz.getDeclaredMethods();
            ArrayList list=new ArrayList<>();
            for(Method m:methods){
                //用Modifier类的函数来判断它是否属被某个修饰符修饰
                //用getModifiers()得到了类(或者字段、或者方法)的访问修饰符int值
                if(Modifier.isPublic(m.getModifiers())){
                    list.add(m);
                }
            }
            return list.toArray(new Method[0]);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            throw new IllegalStateException(e);
        }
    }

    /**
     * 调用传入对象的传入方法(静态方法obj传null)
     * @param obj 传入对象
     * @param method 待调用方法
     * @param args  传入参数
     * @return
     * @throws Exception
     */
    public static Object invoke(Object obj,Method method,Object... args)throws Exception{
        try{
           return method.invoke(obj,args);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            throw new IllegalStateException(e);
        }
    }
}

 

    3.rpc-codec(序列化模块)

对网络传输的数据进行序列化和反序列化,示例中是基于fastjson实现的序列化和反序列,也可以根据其它的依赖或自己定义来实现序列化和反序列化。注:如果是使用IO流来实现序列化和反序列,则可以不需要该模块。

反序列化接口

/**
 * 反序列化接口
 */
public interface Decoder {
    /**
     * 将序列化的字节数组转为对象
     * @param bytes
     * @param clazz
     * @param 
     * @return
     */
    T decode(byte[] bytes,Class clazz);
}

 基于fastjson的反序列化实现

import com.alibaba.fastjson.JSON;

/**
 * 基于JSON的反序列化实现
 */
public class JSONDecoder implements Decoder{
    /**
     * 将序列化的字节数组转为对象
     * @param bytes
     * @param clazz
     * @param 
     * @return
     */
    @Override
    public  T decode(byte[] bytes, Class clazz) {
        return JSON.parseObject(bytes,clazz);
    }
}

 序列化接口

/**
 * 序列化接口
 */
public interface Encoder {
    /**
     * 将对象转为字节数组
     * @param obj
     * @return
     */
    byte[] encode(Object obj);
}

 基于fastjson的序列化实现

import com.alibaba.fastjson.JSON;
/**
 * 基于Json的序列化实现
 */
public class JSONEncoder implements Encoder {
    /**
     * 将对象转为字节数组
     * @param obj
     * @return
     */
    @Override
    public byte[] encode(Object obj) {
        return JSON.toJSONBytes(obj);
    }
}

    4.rpc-proto(协议模块)

对网络传输中请求和响应里的信息进行封装,示例中是自定义的。注:可以根据需求自定义,也可以继承原生HttpRequest和HttpResponse来实现或者使用第三方的。该模块如不需要,可去掉。

网络传输的一个端点

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 表示网络传输的一个端点
 */
@Data//属性getset方法,ToString方法
@AllArgsConstructor//创建一个带所有字段的构造方法
@NoArgsConstructor//创建一个无参构造方法
public class Peer {
    private String host;//网络传输地址
    private int port;//网络传输端口

}

 请求服务类

/**
 * 表示请求服务
 */
@Data//属性getset方法,ToString方法
@AllArgsConstructor//创建一个带所有字段的构造方法
@NoArgsConstructor//创建一个无参构造方法
public class ServiceDescriptor {
    private String clazz;//类
    private String method;//方法
    private String returnType;//返回方式
    private String[] parameterTypes;//返回参数

    public static ServiceDescriptor from(Class clazz, Method method){
        ServiceDescriptor sd=new ServiceDescriptor();
        sd.setClazz(clazz.getName());
        sd.setMethod(method.getName());
        sd.setReturnType(method.getReturnType().getName());
        Class[] parameterClass=method.getParameterTypes();
        String[] parameterArr=new String[parameterClass.length];
        for(int i=0;i请求封装类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 表示RPC的一个请求
 */
@Data//属性getset方法,ToString方法
@AllArgsConstructor//创建一个带所有字段的构造方法
@NoArgsConstructor//创建一个无参构造方法
public class Request {
    private ServiceDescriptor service;//请求服务
    private Object[] parameters;//请求参数

}

 响应封装类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 表示RPC的一个响应
 */
@Data//属性getset方法,ToString方法
@AllArgsConstructor//创建一个带所有字段的构造方法
@NoArgsConstructor//创建一个无参构造方法
public class Response {
    private int code=-1;//响应码,0-成功,非0失败
    private String message="请求失败";//响应信息
    private Object data;//响应数据

    //响应集
    public static final int FAIL=-1;//失败
    public static final int SUCC=0;//成功
    public static final int ERROR=-999;//系统错误
}

    5.rpc-transport(网络通信模块)

该模块是处理服务器和客户端的网络通信方式,本案例使用的是Http协议的网络通信方式,如有需要也可以使用别的通信方式。服务器使用了jetty,如有需要

pom.xml

 
       
            commons-io
            commons-io
           ${commons-io.version}
        
        
            org.eclipse.jetty
            jetty-servlet
            ${jetty-servlet.version}
        
        
            com.wc
            rpc-proto
            ${project.version}
        
    

网络请求服务端接口

/**
 * 网络请求服务端接口
 */
public interface TransportServer {
    /**
     * 初始化
     * @param port
     * @param handler
     */
    void init(int port,RequestHandler handler);
    /**
     * 启动服务并监听
     */
    void satrt();

    /**
     * 结束服务
     */
    void stop();
}

网络请求处理器接口

import java.io.InputStream;
import java.io.OutputStream;

/**
 * 网络请求处理器:处理网络请求的Handler
 */
public interface RequestHandler {
    /**
     *
     * @param inputStream
     * @param outputStream
     */
    void onRequest(InputStream inputStream, OutputStream outputStream);
}

Http网络服务器实现

import lombok.extern.slf4j.Slf4j;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * http协议的网络服务端(http是短连接)
 */
@Slf4j
public class HttpTransportServer implements TransportServer {
    private RequestHandler handler;//请求处理器
    private Server server;//jetty服务器

    @Override
    public void init(int port, RequestHandler handler) {
        this.handler=handler;
        this.server=new Server(port);

        //servlet接收请求
        ServletContextHandler ctx=new ServletContextHandler();
        server.setHandler(ctx);

        //服务台
        ServletHolder holder=new ServletHolder(new RequestServlet());
        ctx.addServlet(holder,"/*");

    }

    @Override
    public void satrt() {
        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    @Override
    public void stop() {
        try {
            server.stop();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    /**
     *
     */
    class RequestServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            log. info("client connect") ;
            ServletInputStream input = req.getInputStream();
            ServletOutputStream output = resp.getOutputStream();

            if(handler!=null){
                handler.onRequest(input,output);
            }
            output.flush();
        }
    }
}

网络请求客户端接口

import com.wc.rpc.proto.Peer;

import java.io.InputStream;

/**
 * 网络请求客户端接口
 */
public interface TransportClient {
    /**
     * 创建连接
     * @param peer
     */
    void connect(Peer peer);

    /**
     * 发送数据,处理响应
     * @param inputStream
     * @return
     */
    InputStream write(InputStream inputStream);

    /**
     * 关闭连接
     */
    void close();

}

 http协议的网络客户端实现

import com.wc.rpc.proto.Peer;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * http协议的网络客户端(http是短连接)
 */
public class HttpTransportClient implements TransportClient{
    private String url;//请求地址+端口
    @Override
    public void connect(Peer peer) {
        this.url="http://"+peer.getHost()+":"+peer.getPort();
    }

    @Override
    public InputStream write(InputStream inputStream) {
        try {
            HttpURLConnection httpConn = (HttpURLConnection) new URL(url).openConnection();
            httpConn.setDoOutput(true);//开启输出
            httpConn.setDoInput(true);//开启读取
            httpConn.setUseCaches(false);//关闭缓存
            httpConn.setRequestMethod("POST");//设置请求方法:POST
            httpConn.connect();//连接
            IOUtils.copy(inputStream,httpConn.getOutputStream());//发送数据
            int resultCode=httpConn.getResponseCode();//获取响应码
            if(HttpURLConnection.HTTP_OK==resultCode){
                return httpConn.getInputStream();
            }else{
                return httpConn.getErrorStream();
            }
        } catch (IOException e) {
            //e.printStackTrace();
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void close() {

    }
}

    6.rpc-server(服务器模块)

该模块负责注册生产者,接收消费者发送过来的请求,对请求进行识别处理并返回组装响应的结果。如果序列化与反序列化未使用自定义的,那该模块的中的相关代码可以去除。

pom.xml

 
        
            com.wc
            rpc-codec
            ${project.version}
        
        
            com.wc
            rpc-common
            ${project.version}
        
        
            com.wc
            rpc-proto
            ${project.version}
        
        
            com.wc
            rpc-transport
            ${project.version}
        
        
            commons-io
            commons-io
            ${commons-io.version}
        
    

server配置

import com.wc.rpc.codec.Decoder;
import com.wc.rpc.codec.Encoder;
import com.wc.rpc.codec.JSONDecoder;
import com.wc.rpc.codec.JSONEncoder;
import com.wc.rpc.transport.HttpTransportServer;
import com.wc.rpc.transport.TransportServer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * server配置
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcServerConfig {
    private Class transportClass= HttpTransportServer.class;
    private Class encodeClass= JSONEncoder.class;
    private Class decodeClass= JSONDecoder.class;
    private int port=3000;//服务器端口

}

生产者对象类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Method;

/**
 * 表示具体服务
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ServiceInstance {
    private Object target;//对象
    private Method method;//方法
}

对象管理类,负责注册生产者和查询对应的对象方法。

import com.wc.rpc.common.utils.ReflectionUtils;
import com.wc.rpc.proto.Request;
import com.wc.rpc.proto.ServiceDescriptor;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 管理rpc暴露的服务
 */
@Slf4j
public class ServiceManager {
    private Map service;

    public ServiceManager(){
        this.service=new ConcurrentHashMap<>();
    }

    /**
     *  将接口和对应的对象绑定到一起,并放入service中
     * @param interfaceClass 接口的class
     * @param bean  接口具体实现的子类的对象
     */
    public  void register(Class interfaceClass,T bean)  {
        try {
            Method[] methods = ReflectionUtils.getPublicMethods(interfaceClass);
            for(Method method:methods){
                ServiceInstance sis = new ServiceInstance(bean, method);
                ServiceDescriptor sd = ServiceDescriptor.from(interfaceClass, method);
                service.put(sd,sis);
                log.info("register service:{} {}",sd.getClazz(),sd.getMethod());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    public ServiceInstance lookup(Request request){
        ServiceDescriptor sd=request.getService();
        return service.get(sd);
    }
}

  Rpc服务器类

import com.wc.rpc.codec.Decoder;
import com.wc.rpc.codec.Encoder;
import com.wc.rpc.common.utils.ReflectionUtils;
import com.wc.rpc.proto.Request;
import com.wc.rpc.proto.Response;
import com.wc.rpc.transport.RequestHandler;
import com.wc.rpc.transport.TransportServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import java.io.InputStream;
import java.io.OutputStream;

@Slf4j
public class RpcServer {
    private RpcServerConfig config;
    private TransportServer netServer;
    private Encoder encoder;
    private Decoder decoder;
    private ServiceManager manager;

    private RequestHandler handler=new RequestHandler(){

        @Override
        public void onRequest(InputStream inputStream, OutputStream outputStream) {
            //生成响应对象
            Response response=new Response();
            try {
               //获取传入数据
               byte[] inBytes = IOUtils.readFully(inputStream, inputStream.available());
               //反序列化生成请求对象
               Request request=decoder.decode(inBytes,Request.class);
               log.info("get Request:{}",request);
               ServiceInstance instance = manager.lookup(request);
               if(instance!=null){
                   //调用方法
                   Object obj =ReflectionUtils.invoke(instance.getTarget(),instance.getMethod(),request.getParameters())
                   response.setData(obj);
                   response.setCode(Response.SUCC);
                   response.setMessage("成功");
               }else{
                   response.setCode(Response.FAIL);
                   response.setMessage("未找到该方法");
               }

            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage(),e);
                response.setCode(Response.ERROR);
                response.setMessage("error:"+e.getClass().getName()+":"+e.getMessage());
            }finally{
                try{
                    byte[] btyes = encoder.encode(response);
                    outputStream.write(btyes);
                }catch (Exception e){
                    e.printStackTrace();
                    log.error(e.getMessage(),e);
                }
            }
        }
    };

    public RpcServer(){
        this(new RpcServerConfig());
    }

    public RpcServer(RpcServerConfig config) {
        try{
            this.config = config;

            //网络服务
            this.netServer= ReflectionUtils.newInstance(config.getTransportClass());
            this.netServer.init(config.getPort(),this.handler);
            //序列化
            this.encoder=ReflectionUtils.newInstance(config.getEncodeClass());
            this.decoder=ReflectionUtils.newInstance(config.getDecodeClass());

            //服务管理
            this.manager=new ServiceManager();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    /**
     * 注册方法
     * @param interfaceClass
     * @param interfaceImplClass
     * @param 
     */
    public  void register(Class interfaceClass,Class interfaceImplClass)  {
        try {
            T bean= (T) interfaceImplClass.newInstance();
            manager.register(interfaceClass,bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动方法
     */
    public void start(){
        netServer.satrt();
    }

    /**
     * 停止方法
     */
    public void stop(){
        netServer.stop();
    }
}

    7.rpc-client(客户端模块)

该模块负责连接服务器,将请求方法发送给服务器,对返回的结果进行解析并返给消费者。如果序列化与反序列化未使用自定义的,那该模块的中的相关代码可以去除。

pom.xml

 
        
            com.wc
            rpc-codec
            ${project.version}
        
        
            com.wc
            rpc-common
            ${project.version}
        
        
            com.wc
            rpc-proto
            ${project.version}
        
        
            com.wc
            rpc-transport
            ${project.version}
        
        
            commons-io
            commons-io
            ${commons-io.version}
        
    

客户端配置

import com.wc.rpc.codec.Decoder;
import com.wc.rpc.codec.Encoder;
import com.wc.rpc.codec.JSONDecoder;
import com.wc.rpc.codec.JSONEncoder;
import com.wc.rpc.proto.Peer;
import com.wc.rpc.transport.HttpTransportClient;
import com.wc.rpc.transport.TransportClient;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

/**
 * client配置
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcClientConfig {
    private Class transportClass= HttpTransportClient.class;
    private Class encodeClass= JSONEncoder.class;
    private Class decodeClass= JSONDecoder.class;
    private Class selectorClass=RandomTransportSelector.class;
    private int connectCount=1;
    private List servers= Arrays.asList(new Peer("127.0.0.1",3000));
}

连接服务器的接口 

import com.wc.rpc.proto.Peer;
import com.wc.rpc.transport.TransportClient;
import java.util.List;

/**
 * 表示选择哪个server去连接
 */
public interface TransportSelector {

    /**
     * 初始化selector
     * @param peers 可以连接的server端点信息
     * @param count client与server可以建立多少个连接
     * @param clazz client实现类的class
     */
    void init(List peers,int count,Class clazz);
    /**
     * 关闭selector
     */
    void close();

    /**
     * 选择一个transport与server交互
     * @return
     */
    TransportClient select();

    /**
     * 释放用完的client
     * @param client
     */
    void relase(TransportClient client);
    
}

 TransportSelector的实现类,用于存储已经连接好的client

import com.wc.rpc.common.utils.ReflectionUtils;
import com.wc.rpc.proto.Peer;
import com.wc.rpc.transport.TransportClient;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * TransportSelector的实现类
 */
@Slf4j
public class RandomTransportSelector implements TransportSelector {
    /**
     * 用于存储已经连接好的client
     */
    private List clients;
    @Override
    public synchronized void init(List peers, int count, Class clazz) {
        count=Math.max(count,1);//两者取最大
        try {
            for(Peer peer:peers){
                for(int i=0;i();
    }
}

rpc客户端类

import com.wc.rpc.codec.Decoder;
import com.wc.rpc.codec.Encoder;
import com.wc.rpc.common.utils.ReflectionUtils;
import com.wc.rpc.proto.Peer;
import com.wc.rpc.proto.Request;
import com.wc.rpc.proto.Response;
import com.wc.rpc.proto.ServiceDescriptor;
import com.wc.rpc.transport.TransportClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Slf4j
public class RpcClient {
    private RpcClientConfig config;
    private Encoder encoder;
    private Decoder decoder;
    private TransportSelector selector;

    /**
     * 无参构造方法
     */
    public RpcClient(){
        this(new RpcClientConfig());
    }
    /**
     * 有参构造方法
     */
    public RpcClient(RpcClientConfig rpcClientConfig){
        try{
            this.config=rpcClientConfig;
            this.decoder=ReflectionUtils.newInstance(this.config.getDecodeClass());
            this.encoder=ReflectionUtils.newInstance(this.config.getEncodeClass());
            this.selector=ReflectionUtils.newInstance(this.config.getSelectorClass());
            this.selector.init(this.config.getServers(),this.config.getConnectCount(),this.config.getTransportClass());
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    /**
     * 获取接口代理对象
     * @param clazz
     * @return
     */
    public  T getProxy(Class clazz){
        return (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //构造请求
                Request request=new Request();
                request.setService(ServiceDescriptor.from(clazz,method));
                request.setParameters(args);
                //通过网络把请求发送给server,等待server的响应
                Response response=invokeRemote(request);
                //获取数据
                if(response==null||response.getCode()!=0){
                    throw new IllegalStateException("fail:"+response);
                }
                return response.getData();
            }
            /**
             * 网络传输
             * @param request
             * @return
             */
            private Response invokeRemote(Request request) {
                TransportClient client=null;
                Response response=null;
                try{
                    client=selector.select();
                    byte[] bytes = encoder.encode(request);
                    //把请求发送给server,等待server的响应
                    Peer peer = config.getServers().get(0);
                    client.connect(peer);
                    InputStream revice = client.write(new ByteArrayInputStream(bytes));
                    //返回结果
                    byte[] resBytes = IOUtils.readFully(revice, revice.available());
                    response = decoder.decode(resBytes, Response.class);
                }catch (Exception e){
                    e.printStackTrace();
                    log.error(e.getMessage(),e);
                    response=new Response();
                    response.setCode(Response.ERROR);
                    response.setMessage("invokeRemote Error:"+e.getClass()+":"+e.getMessage());
                    return response;
                }finally {
                    if(client!=null){
                        selector.relase(client);
                    }
                }
                return response;
            }
        });
    }
}

    8.rpc-demo(示例模块)

模拟外部调用

pom.xml


        
            com.wc
            rpc-client
            ${project.version}
        
        
            com.wc
            rpc-server
            ${project.version}
        
    

示例接口

public interface DemoService {
    /**
     * 示例方法01
     * @param a
     * @param b
     * @return
     */
    String method01(int a, int b);

    /**
     * 示例方法02
     * @param c
     * @param d
     * @return
     */
    String method02(int c, int d);

}

示例接口实现类

public class DemoServiceImpl implements DemoService {
    @Override
    public String method01(int a, int b) {
        return "a="+a+",b="+b;
    }

    @Override
    public String method02(int c, int d) {
         return "c="+c+",d="+d;
    }
}

示例中的生产者 

import com.wc.rpc.server.RpcServer;
import com.wc.rpc.server.RpcServerConfig;

public class Provider{
    public static void main(String[] args){
        try{
            //配置服务器
            RpcServerConfig config=new RpcServerConfig();
            config.setDecodeClass(JSONDecoder.class);
            config.setEncodeClass(JSONEncoder.class);
            config.setTransportClass(HttpTransportServer.class);
            config.setPort(3000);
            //生成带配置的服务器对象
            RpcServer server=new RpcServer(config);
            //将接口与对应的实现放入服务注册中心
            server.register(DemoService.class,DemoServiceImpl.class);
            //启动
            server.start();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

示例中的消费者

import com.wc.rpc.client.RandomTransportSelector;
import com.wc.rpc.client.RpcClient;
import com.wc.rpc.client.RpcClientConfig;
import com.wc.rpc.codec.JSONDecoder;
import com.wc.rpc.codec.JSONEncoder;
import com.wc.rpc.proto.Peer;
import com.wc.rpc.transport.TransportClient;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class Consumer{

    public static void main(String[] args) throws Exception {
        //配置客户端,和连接的服务器
        RpcClientConfig config=new RpcClientConfig();
        config.setDecodeClass(JSONDecoder.class);
        config.setEncodeClass(JSONEncoder.class);
        config.setTransportClass(HttpTransportClient.class);
        config.setSelectorClass(RandomTransportSelector.class);
        List list=new ArrayList();
        list.add(new Peer("127.0.0.1",3000));
        config.setServers(list);
        //生成带配置的客户端对象
        RpcClient client = new RpcClient(config);
        //通过动态代理调用服务注册中心里相应的方法实现
        CalcService service =client.getProxy(DemoService.class);
        String method01= service.method01(1, 2);
        String method02= service.method02(10, 5);
        log.info("method01:"+method01);
        log.info("method02:"+method02);
    }
}

 

总结

难点:动态代理。
 

你可能感兴趣的:(java,RPC)