简单聊一下RPC(Remote Procedure Call) ,远程过程调用,底层基于TCP/IP通信,下图是简单的微服务架构,会员服务需要查询当前会员下面的订单信息,则会涉及会员服务调用订单服务:
1、用户终端访问主站首页;
2、用户登陆,调用会员的登陆验证服务;
3、用户查看我的订单,调用会员服务的订单列表查询-->这时涉及会员服务调用订单服务;
技术选型:
1)可以采用HTTP访问,https://域名/接口/参数
2)可以采用基于Socket通信的RPC协议,实现会员服务与订单服务的通信。
1、首先将订单服务接口打包,供会员服务引用:
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对象中,调用服务的服务接口,并将结果通过流,回写到客户端,整个流程看起来,就像在调用客户端本地的方法。
代码示例,代码骨架基于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);
}
}
欢迎留言探讨,一起走向人生巅峰。。。。