zoukankan      html  css  js  c++  java
  • JDK动态代理在RPC框架中的应用

    RPC框架中一般都有3个角色:服务提供者、服务消费者和注册中心。服务提供者将服务注册到注册中心,服务消费者从注册中心拉取服务的地址,并根据服务地址向服务提供者发起RPC调用。动态代理在这个RPC调用的过程中有什么作用?对于服务消费者,一般只会依赖服务接口,而服务的具体实现是在服务提供者这一端的,服务消费者和服务提供者分别部署在不同的机器上,服务消费者调用接口中的方法时怎么能够得到结果呢?JDK的动态代理就派上用场了。服务消费者使用JDK的动态代理技术,可以创建接口的代理对象,并在回调函数中将自己要调用的接口名称、方法签名信息通过http或者tcp的方式发送给服务提供者,服务提供者再通过反射的方式调用本地的服务,最后将结果通过http或tcp的方式返回给消费者。

    下面是一个简单的演示程序:

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 import java.lang.reflect.Proxy;
     4 import java.util.HashMap;
     5 import java.util.Map;
     6 
     7 /**
     8  * 动态代理在RPC中的使用
     9  *
    10  * @author syj
    11  */
    12 public class JDKProxyTest {
    13 
    14     // ---------------------------  模拟RPC客户端  ---------------------------
    15 
    16     // 客户端依赖服务端的接口(实现类在服务端)
    17     private static IUserService userService;
    18 
    19     public static void main(String[] args) {
    20         // 根据接口创建代理对象
    21         userService = (IUserService) Proxy.newProxyInstance(
    22                 JDKProxyTest.class.getClassLoader(),
    23                 new Class[]{IUserService.class},
    24                 new InvocationHandler() {
    25                     // 在回调方法模拟进行RPC调用(通过http或者tcp与服务端通信)
    26                     @Override
    27                     public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    28                         return rpcInvoke(IUserService.class.getSimpleName(), method.getName(), method.getParameterTypes(), params);
    29                     }
    30                 }
    31         );
    32         // 本地调用
    33         String result = userService.sayHello("hello");
    34         System.out.println(">>>> result =" + result);
    35     }
    36 
    37 
    38     // ---------------------------  模拟RPC服务端  ---------------------------
    39 
    40     /**
    41      * 反射调用
    42      *
    43      * @param methodName     方法名称
    44      * @param parameterTypes 方法参数类型
    45      * @param parameters     方法参数
    46      * @return
    47      */
    48     private static Object rpcInvoke(String interfaceName, String methodName, Class<?>[] parameterTypes, Object[] parameters) {
    49         Object result = null;
    50         try {
    51             // 根据接口名称从Bean容器中获取Bean实例
    52             Object serviceBean = beanMap.get(interfaceName);
    53             // 反射调用
    54             Class<?> serviceClass = serviceBean.getClass();
    55             Method method = serviceClass.getMethod(methodName, parameterTypes);
    56             method.setAccessible(true);
    57             // 得到调用结果
    58             result = method.invoke(serviceBean, parameters);
    59         } catch (Exception e) {
    60             e.printStackTrace();
    61         }
    62         return result;
    63     }
    64 
    65     // 模拟Bean容器, key为接口名称, value为bean实例
    66     private static Map<String, Object> beanMap = new HashMap<String, Object>() {{
    67         put("IUserService", new UserServiceImpl());
    68     }};
    69 }

    接口(服务提供者和服务的消费者都会依赖该接口):

    1 public interface IUserService {
    2     String sayHello(String content);
    3 }

    服务提供者实现类:

    public class UserServiceImpl implements IUserService {
        @Override
        public String sayHello(String content) {
            return content + "::" + System.currentTimeMillis();
        }
    }

    其实,JDK的动态代理技术,不仅可以应用在RPC框架中,也可以应用在所有基于客户端和服务端通信的架构中,比如微服务架构中的注册中心、配置中心、消息中心等。

  • 相关阅读:
    转义将正文中换行符
    THINKPHP短链接设置方法(路由设置)
    MEMCACHE分布式算法(PHP)
    win7下memCache安装过程
    JQUERY根据值将input控件选中!
    Thinkphp CURD中的where方法
    SQL语法LPAD和RPAD
    Linux查看docker容器日志
    Linux中清空docker容器日志
    错误记录——fail: Microsoft.AspNetCore.Server.Kestrel[13]
  • 原文地址:https://www.cnblogs.com/jun1019/p/10952447.html
Copyright © 2011-2022 走看看