资讯专栏INFORMATION COLUMN

dubbo源码解析(二十八)远程调用——memcached协议

Faremax / 1592人阅读

摘要:源码分析一该类继承,是协议实现的核心。属性默认端口号不支持服务暴露可以看到,服务暴露方法直接抛出异常。后记该部分相关的源码解析地址该文章讲解了远程调用中关于协议实现的部分,逻辑比较简单。

远程调用——memcached协议
目标:介绍memcached协议的设计和实现,介绍dubbo-rpc-memcached的源码。
前言

dubbo实现memcached协议是基于Memcached,Memcached 是一个高效的 KV 缓存服务器,在dubbo中没有涉及到关于memcached协议的服务暴露,只有服务引用,因为在访问Memcached服务器时,Memcached客户端可以在服务器上存储也可以获取。

源码分析 (一)MemcachedProtocol

该类继承AbstractProtocol,是memcached协议实现的核心。

1.属性
/**
 * 默认端口号
 */
public static final int DEFAULT_PORT = 11211;
2.export
@Override
public  Exporter export(final Invoker invoker) throws RpcException {
    // 不支持memcached服务暴露
    throw new UnsupportedOperationException("Unsupported export memcached service. url: " + invoker.getUrl());
}

可以看到,服务暴露方法直接抛出异常。

3.refer
@Override
public  Invoker refer(final Class type, final URL url) throws RpcException {
    try {
        // 获得地址
        String address = url.getAddress();
        // 获得备用地址
        String backup = url.getParameter(Constants.BACKUP_KEY);
        // 把备用地址拼接上
        if (backup != null && backup.length() > 0) {
            address += "," + backup;
        }
        // 创建Memcached客户端构造器
        MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(address));
        // 创建客户端
        final MemcachedClient memcachedClient = builder.build();
        // 到期时间参数配置
        final int expiry = url.getParameter("expiry", 0);
        // 获得值命令
        final String get = url.getParameter("get", "get");
        // 添加值命令根据类型来取决是put还是set
        final String set = url.getParameter("set", Map.class.equals(type) ? "put" : "set");
        // 删除值命令
        final String delete = url.getParameter("delete", Map.class.equals(type) ? "remove" : "delete");
        return new AbstractInvoker(type, url) {
            @Override
            protected Result doInvoke(Invocation invocation) throws Throwable {
                try {
                    // 如果是获取方法名的值
                    if (get.equals(invocation.getMethodName())) {
                        // 如果参数长度不等于1,则抛出异常
                        if (invocation.getArguments().length != 1) {
                            throw new IllegalArgumentException("The memcached get method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
                        }
                        // 否则调用get方法来获取
                        return new RpcResult(memcachedClient.get(String.valueOf(invocation.getArguments()[0])));
                    } else if (set.equals(invocation.getMethodName())) {
                        // 如果参数长度不为2,则抛出异常
                        if (invocation.getArguments().length != 2) {
                            throw new IllegalArgumentException("The memcached set method arguments mismatch, must be two arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
                        }
                        // 无论任何现有值如何,都在缓存中设置一个对象
                        memcachedClient.set(String.valueOf(invocation.getArguments()[0]), expiry, invocation.getArguments()[1]);
                        return new RpcResult();
                    } else if (delete.equals(invocation.getMethodName())) {
                        // 删除操作只有一个参数,如果参数长度不等于1,则抛出异常
                        if (invocation.getArguments().length != 1) {
                            throw new IllegalArgumentException("The memcached delete method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
                        }
                        // 删除某个值
                        memcachedClient.delete(String.valueOf(invocation.getArguments()[0]));
                        return new RpcResult();
                    } else {
                        // 不支持的操作
                        throw new UnsupportedOperationException("Unsupported method " + invocation.getMethodName() + " in memcached service.");
                    }
                } catch (Throwable t) {
                    RpcException re = new RpcException("Failed to invoke memcached service method. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url + ", cause: " + t.getMessage(), t);
                    if (t instanceof TimeoutException || t instanceof SocketTimeoutException) {
                        re.setCode(RpcException.TIMEOUT_EXCEPTION);
                    } else if (t instanceof MemcachedException || t instanceof IOException) {
                        re.setCode(RpcException.NETWORK_EXCEPTION);
                    }
                    throw re;
                }
            }

            @Override
            public void destroy() {
                super.destroy();
                try {
                    // 关闭客户端
                    memcachedClient.shutdown();
                } catch (Throwable e) {
                    logger.warn(e.getMessage(), e);
                }
            }
        };
    } catch (Throwable t) {
        throw new RpcException("Failed to refer memcached service. interface: " + type.getName() + ", url: " + url + ", cause: " + t.getMessage(), t);
    }
}

该方法是服务引用方法,基于MemcachedClient的get、set、delete方法来对应Memcached的get、set、delete命令进行对值的操作。

后记
该部分相关的源码解析地址:https://github.com/CrazyHZM/i...

该文章讲解了远程调用中关于memcached协议实现的部分,逻辑比较简单。接下来我将开始对rpc模块关于redis协议部分进行讲解。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/61750.html

相关文章

  • dubbo源码解析(四十八)异步化改造

    摘要:大揭秘异步化改造目标从源码的角度分析的新特性中对于异步化的改造原理。看源码解析四十六消费端发送请求过程讲到的十四的,在以前的逻辑会直接在方法中根据配置区分同步异步单向调用。改为关于可以参考源码解析十远程通信层的六。 2.7大揭秘——异步化改造 目标:从源码的角度分析2.7的新特性中对于异步化的改造原理。 前言 dubbo中提供了很多类型的协议,关于协议的系列可以查看下面的文章: du...

    lijinke666 评论0 收藏0
  • dubbo源码解析二十七)远程调用——injvm本地调用

    摘要:远程调用本地调用目标介绍本地调用的设计和实现,介绍的源码。前言是一个远程调用的框架,但是它没有理由不支持本地调用,本文就要讲解关于本地调用的实现。服务暴露者集合取消暴露调用父类的取消暴露方法从集合中移除二该类继承了类,是本地调用的实现。 远程调用——injvm本地调用 目标:介绍injvm本地调用的设计和实现,介绍dubbo-rpc-injvm的源码。 前言 dubbo是一个远程调用的...

    sean 评论0 收藏0
  • dubbo源码解析(四十六)消费端发送请求过程

    摘要:可以参考源码解析二十四远程调用协议的八。十六的该类也是用了适配器模式,该类主要的作用就是增加了心跳功能,可以参考源码解析十远程通信层的四。二十的可以参考源码解析十七远程通信的一。 2.7大揭秘——消费端发送请求过程 目标:从源码的角度分析一个服务方法调用经历怎么样的磨难以后到达服务端。 前言 前一篇文章讲到的是引用服务的过程,引用服务无非就是创建出一个代理。供消费者调用服务的相关方法。...

    fish 评论0 收藏0
  • dubbo源码解析二十九)远程调用——redis协议

    摘要:源码分析一该类继承了类,是协议实现的核心。属性默认端口号不支持协议的服务暴露,抛出异常可以看到不支持服务暴露。后记该部分相关的源码解析地址该文章讲解了远程调用中关于协议实现的部分,逻辑比较简单。 远程调用——redis协议 目标:介绍redis协议的设计和实现,介绍dubbo-rpc-redis的源码。 前言 dubbo支持的redis协议是基于Redis的,Redis 是一个高效的 ...

    mating 评论0 收藏0
  • dubbo源码解析(四十七)服务端处理请求过程

    摘要:而存在的意义就是保证请求或响应对象可在线程池中被解码,解码完成后,就会分发到的。 2.7大揭秘——服务端处理请求过程 目标:从源码的角度分析服务端接收到请求后的一系列操作,最终把客户端需要的值返回。 前言 上一篇讲到了消费端发送请求的过程,该篇就要将服务端处理请求的过程。也就是当服务端收到请求数据包后的一系列处理以及如何返回最终结果。我们也知道消费端在发送请求的时候已经做了编码,所以我...

    yzzz 评论0 收藏0

发表评论

0条评论

Faremax

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<