码迷,mamicode.com
首页 > 其他好文 > 详细

Dubbo token invalid

时间:2015-08-12 09:06:32      阅读:551      评论:0      收藏:0      [点我收藏+]

标签:

dubbo开启token服务后,使用集群容错策略为FailoverClusterInvoker,当出现服务调用失败进行转移,重试其它服务器时,会出现token invalid错误,provider会拒绝服务调用。

原因:

消费端:

1、com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke:

   for (int i = 0; i < len; i++) {
   //重试时,进行重新选择,避免重试时invoker列表已发生变化.
   //注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
   if (i > 0) {
      checkWheatherDestoried();
      copyinvokers = list(invocation);
      //重新检查一下
      checkInvokers(copyinvokers, invocation);
   }
     Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
     invoked.add(invoker);
     RpcContext.getContext().setInvokers((List)invoked);
  try {
           
                if (le != null && logger.isWarnEnabled()) {
                    logger.warn("Although retry the method " + invocation.getMethodName()
                            + " in the service " + getInterface().getName()
                            + " was successful by the provider " + invoker.getUrl().getAddress()
                            + ", but there have been failed providers " + providers 
                            + " (" + providers.size() + "/" + copyinvokers.size()
                            + ") from the registry " + directory.getUrl().getAddress()
                            + " on the consumer " + NetUtils.getLocalHost()
                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
                            + le.getMessage(), le);
                }
                return result;
            } catch (RpcException e) {
                if (e.isBiz()) { // biz exception.
                    throw e;
                }
                le = e;
            } catch (Throwable e) {
                le = new RpcException(e.getMessage(), e);
            } finally {
                providers.add(invoker.getUrl().getAddress());
            }
	
2、com.alibaba.dubbo.rpc.protocol.AbstractInvoker#invoke
  RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);
        if (attachment != null && attachment.size() > 0) {
            invocation.addAttachmentsIfAbsent(attachment);  //添加相关参数到附件attachments,如token
        }
        Map<String, String> context = RpcContext.getContext().getAttachments();
        if (context != null) {
            invocation.addAttachmentsIfAbsent(context);
        }
3、addAttachmentsIfAbsent实现:
    public void setAttachmentIfAbsent(String key, String value) {
        if (attachments == null) {
            attachments = new HashMap<String, String>();
        }
        if (! attachments.containsKey(key)) {  //key不存在时才进行赋值,因此不能进行覆盖操作
        	attachments.put(key, value);
        }
    }

服务提供方:

public class TokenFilter implements Filter {

   public Result invoke(Invoker<?> invoker, Invocation inv)
         throws RpcException {
       String token = invoker.getUrl().getParameter(Constants.TOKEN_KEY);
       if (ConfigUtils.isNotEmpty(token)) {
           Class<?> serviceType = invoker.getInterface();
           Map<String, String> attachments = inv.getAttachments();//解析attachments 
          String remoteToken = attachments == null ? null : attachments.get(Constants.TOKEN_KEY);
          if (! token.equals(remoteToken)) {
             throw new RpcException("Invalid token! Forbid invoke remote service " + serviceType + " method " + inv.getMethodName() + "() from consumer " + RpcContext.getContext().getRemoteHost() + " to provider "  + RpcContext.getContext().getLocalHost());
          }
       }
      return invoker.invoke(inv);
   }

}

通过上面的代码分析可知,当消费者调用服务方服务出现超时进行失败重连时,要重连的Invoker的token没有覆盖上一次的invoker的token,而服务端比较token时比较的是attachment, 进而出现token invalid错误。相当于失败重连无效.

错误现象:

1、请求超时,此时token是一致的
telnet=invoke,status,replacetoken&timeout=1000&timestamp=1418813410249&token=020f16e2-e060-4c85-a31a-017aa0ee268c&version=1.0, cause: Waiting server-side response timeout. start time: 2014-12-17 21:42:26.735, end time: 2014-12-17 21:42:27.736, client elapsed: 0 ms, server elapsed: 1001 ms, timeout: 1000 ms, request: Request [id=27484, version=2.0.0, twoway=true, event=false, broken=false, data=RpcInvocation [.........................], attachments={token=020f16e2-e060-4c85-a31a-017aa0ee268c,
 
。。。。。。。
2、失败重连,此时附件token与url的不一致
....................&pid=29465&revision=1.0.1&side=consumer&status=spring,load&telnet=invoke,status,replacetoken&timeout=1000&timestamp=1418813410249
&token=0f3103ad-ac7b-4906-897c-b51e69ab3b96&version=1.0 -> RpcInvocation [..................................], 
attachments={token=020f16e2-e060-4c85-a31a-017aa0ee268c, 
。。。。。。。
3、出现token invalid
com.alibaba.dubbo.rpc.RpcException: Invalid token! Forbid invoke remote service interface


Dubbo token invalid

标签:

原文地址:http://my.oschina.net/mingyuanwang/blog/490979

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!