微服务架构-基于注解RPC通信的案例分享

一、前言

简单聊一下RPC(Remote  Procedure  Call)  ,远程过程调用,底层基于TCP/IP通信,下图是简单的微服务架构,会员服务需要查询当前会员下面的订单信息,则会涉及会员服务调用订单服务:

1、用户终端访问主站首页;

2、用户登陆,调用会员的登陆验证服务;

3、用户查看我的订单,调用会员服务的订单列表查询-->这时涉及会员服务调用订单服务;

      技术选型:

      1)可以采用HTTP访问,https://域名/接口/参数

      2)可以采用基于Socket通信的RPC协议,实现会员服务与订单服务的通信。

微服务架构-基于注解RPC通信的案例分享_第1张图片

 

 二、案例分享:

  1、首先将订单服务接口打包,供会员服务引用:

       微服务架构-基于注解RPC通信的案例分享_第2张图片

package org.example;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-22 23:52
 **/
public interface IOrderService {
      String  queryOrderList();
      String  orderById(String id);
}

系统间通信的数据结构:

package org.example;

import java.io.Serializable;
import java.util.Arrays;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 00:39
 **/
public class RpcRequest implements Serializable {
    private static final long serialVersionUID = 1502241954359378124L;
    private String className;
    private String methodName;
    private Object[] args;
    private Class[] types;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Object[] getArgs() {
        return args;
    }

    public void setArgs(Object[] args) {
        this.args = args;
    }

    public Class[] getTypes() {
        return types;
    }

    public void setTypes(Class[] types) {
        this.types = types;
    }

    @Override
    public String toString() {
        return "RpcRequest{" +
                "className='" + className + '\'' +
                ", methodName='" + methodName + '\'' +
                ", args=" + Arrays.toString(args) +
                ", types=" + Arrays.toString(types) +
                '}';
    }
}

 

2、会员服务代码开发:

     会员服务在本次的业务场景中,充当着客户端的角色,咱们需要知道服务端的SocketServer的监听端口,另外通过订单的接口,咱们可以通过动态代理,在h对象中,调用服务的服务接口,并将结果通过流,回写到客户端,整个流程看起来,就像在调用客户端本地的方法。

微服务架构-基于注解RPC通信的案例分享_第3张图片

微服务架构-基于注解RPC通信的案例分享_第4张图片 

代码示例,代码骨架基于SpringBoot:

自定义注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @program: UserService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 23:36
 **/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JasonReference {
}

 动态代理,实现接口的注入

package org.example;

import org.example.annotation.JasonReference;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * @program: UserService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-24 00:04
 **/
@Component
public class InintialProxy  implements BeanPostProcessor {

    @Autowired
    private  RemoteInvocationHandler  handler;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        Field[]  fields=bean.getClass().getDeclaredFields();
        for(Field field:fields)
        {
            field.setAccessible(true);
            if(field.isAnnotationPresent(JasonReference.class))
            {
                Object proxy= Proxy.newProxyInstance(field.getType().getClassLoader(),new Class[]{field.getType()},handler);
                try {
                    field.set(bean,proxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
         return  bean;
    }
}

package org.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.Socket;
import java.nio.channels.SocketChannel;

/**
 * @program: UserService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 00:34
 **/
@Component
public class RemoteInvocationHandler  implements InvocationHandler {
    @Value("${jason.host}")
    public String host;

    @Value("${jason.port}")
    public  int port;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        RpcNetTransport   rpcNetTransport=new RpcNetTransport(host,port);
        Socket socket=rpcNetTransport.newConn();

        RpcRequest   request=new RpcRequest();
        request.setArgs(args);
        request.setClassName(method.getDeclaringClass().getName());
        request.setTypes(method.getParameterTypes());
        request.setMethodName(method.getName());
        Object obj =rpcNetTransport.send(request);
        return  obj;
    }
}

 底层socket

package org.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 * @program: UserService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 00:31
 **/
public class RpcNetTransport{
    private  String host;
    private  int port;

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

    public  Socket  newConn() throws IOException {
        Socket  socket=new Socket(host,port);
        return  socket;
    }
    public  Object    send(RpcRequest  rpcRequest)
    {
        ObjectInputStream objectInputStream=null;
        ObjectOutputStream  objectOutputStream=null;
        Object obj=null;
        try {
            Socket  socket=newConn();
            //IO操作
            objectOutputStream=new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(rpcRequest);
            objectOutputStream.flush();

            objectInputStream=new ObjectInputStream( socket.getInputStream());
            obj=objectInputStream.readObject();
            System.out.println("获取服务端返回消息:"+obj);


        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            return obj;
        }
    }
}

对客的Rest服务:

package org.example;

import org.example.annotation.JasonReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @program: UserService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 23:37
 **/
@RestController
public class TestController {
      @JasonReference
      private IOrderService  orderService;

      @GetMapping("/test")
      public String test()
      {
            return orderService.queryOrderList();
      }
}

 配置文件:

jason.host=localhost
jason.port=8089

spring.application.name==user-service
server.port=8080

3、订单服务代码开发:

     自定义注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 21:26
 **/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface JasonRpcService {
}

 服务的实现类

package org.example.service;

import org.example.IOrderService;
import org.example.annotation.JasonRpcService;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-22 23:56
 **/
@JasonRpcService
public class OrderServiceImpl  implements IOrderService {
    @Override
    public String queryOrderList() {
        return "queryOrderList....";
    }

    @Override
    public String orderById(String id) {
        return "orderById......";
    }
}

  服务的自动注册

package org.example.support;

import org.example.RpcRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 21:55
 **/
public class Mediator {
    private static Map map=new ConcurrentHashMap<>();
    public static Lock lock=new ReentrantLock();
    private static Mediator  mediator;
    private static Object object=new Object();
    public static void  register(String key,BeanMethod beanMethod)
    {
        try{
            lock.lock();
            if(map.size()==0||!map.containsKey(key))
            {
                System.out.println("加载  key="+key+"---beanMethod="+beanMethod);
                map.put(key,beanMethod);
            }
        }finally {
            lock.unlock();
        }
    }
    public static Mediator  getInstance()
    {
        if(mediator==null)
        {
            synchronized (object)
            {
                if(mediator==null)
                {
                    mediator=new Mediator();
                }
            }
        }
        return mediator;
    }
    public static Object  processor(RpcRequest  request)
    {
        if(request==null)
        {
            System.out.println("客户端传递的request为Null");
            return null;
        }
        String  key=request.getClassName()+"."+request.getMethodName();
        System.out.println("容器中查找,key="+key);
        BeanMethod  beanMethod=map.get(key);
        if(beanMethod==null)
        {
            System.out.println("容器中没有命中,返回空");
            return null;
        }

        Object obj=beanMethod.getBean();
        Method method=beanMethod.getMethod();
        Object response=null;
        try {
           response= method.invoke(obj,request.getArgs());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            return  response;
        }
    }

}

package org.example.support;

import org.example.annotation.JasonRpcService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 21:57
 **/
@Component
public class InitialMediatiator  implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean.getClass().isAnnotationPresent(JasonRpcService.class))
        {
            Method[]  methods=bean.getClass().getDeclaredMethods();
            System.out.println("容器初始化加载开始...");
            for(Method method:methods)
            {
                String key=bean.getClass().getInterfaces()[0].getName()+"."+method.getName();
                BeanMethod  beanMethod=new BeanMethod();
                beanMethod.setBean(bean);
                beanMethod.setMethod(method);
                Mediator.register(key,beanMethod);

            }
        }
        return bean ;
    }
}


package org.example.support;

import java.lang.reflect.Method;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 21:56
 **/
public class BeanMethod {
    private Object bean;
    private Method method;

    public Object getBean() {
        return bean;
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }
}

 底层Socket&服务的自动发布

package org.example;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 00:45
 **/
public class RpcProxyServer {
       private final ExecutorService   executorService= Executors.newFixedThreadPool(10);
       public void publish(int port)
       {
           try {
               ServerSocket   serverSocket=new ServerSocket(port);
               while (true)
               {
                   Socket socket=serverSocket.accept();
                   executorService.execute(new TaskExecutor(socket));
               }
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
}


package org.example;

import org.example.support.InitialMediatiator;
import org.example.support.Mediator;

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

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 00:48
 **/
public class TaskExecutor implements Runnable{

    private Socket socket;

    public TaskExecutor(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        ObjectInputStream objectInputStream=null;
        ObjectOutputStream objectOutputStream=null;
        try {
            objectInputStream=new ObjectInputStream(socket.getInputStream());
            RpcRequest  rpcRequest=(RpcRequest)objectInputStream.readObject();
            System.out.println("获取客户端请求:"+rpcRequest.toString());

            Mediator mediator=Mediator.getInstance();
            Object obj=Mediator.processor(rpcRequest);
            System.out.println("服务端响应:"+obj);
            objectOutputStream=new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(obj);
            objectOutputStream.flush();
        } catch (Exception e) {
            try
            {
                if(objectInputStream!=null)
               {
                objectInputStream.close();
                }
                if(objectOutputStream!=null)
                {
                    objectOutputStream.close();
                }

            }catch (Exception m){
                m.printStackTrace();
            }

        }
    }
//    private Object invoke(RpcRequest  request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//        Class  clazz=Class.forName(request.getClassName());
//        Method method=clazz.getMethod(request.getMethodName(),request.getTypes());
//        return   method.invoke(request.getArgs());
//    }
}


服务的自动发布
package org.example;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @program: OrderService
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-23 22:16
 **/
@Component
public class SocketServerInitial  implements ApplicationListener {
    private final ExecutorService executorService= Executors.newFixedThreadPool(10);
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        try {
            System.out.println("发布服务端服务开始:");
            ServerSocket serverSocket=new ServerSocket(8089);
            while (true)
            {
                Socket socket=serverSocket.accept();
                executorService.execute(new TaskExecutor(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务启动:

package org.example;

import org.example.service.OrderServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Hello world!
 *
 */
@Configuration
@ComponentScan("org.example")
public class App 
{
    public static void main( String[] args )
    {
        //1.0版本
//        RpcProxyServer  rpcProxyServer=new RpcProxyServer();
//        rpcProxyServer.publish(8080);

        //2.0版本
        ApplicationContext  applicationContext=new AnnotationConfigApplicationContext(App.class);
    }
}

三、运行结果:

 

微服务架构-基于注解RPC通信的案例分享_第5张图片

欢迎留言探讨,一起走向人生巅峰。。。。

 

你可能感兴趣的:(分布式架构)