public void destroy() {
   super.destroy();
   try {
     expireFuture.cancel(true);
   } catch (Throwable t) {
     logger.warn(t.getMessage(), t);
   }
   try {
     for (RedisRegistryNotifier notifier : notifiers.values()) {
       notifier.shutdown();
     }
   } catch (Throwable t) {
     logger.warn(t.getMessage(), t);
   }
   for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) {
     JedisPool jedisPool = entry.getValue();
     try {
       jedisPool.destroy();
     } catch (Throwable t) {
       logger.warn(
           "Failed to destroy the redis registry client. registry: "
               + entry.getKey()
               + ", cause: "
               + t.getMessage(),
           t);
     }
   }
 }
예제 #2
0
 public void destroy() {
   if (logger.isInfoEnabled()) {
     logger.info("Destroy registry:" + getUrl());
   }
   Set<URL> destroyRegistered = new HashSet<URL>(getRegistered());
   if (!destroyRegistered.isEmpty()) {
     for (URL url : new HashSet<URL>(getRegistered())) {
       if (url.getParameter(Constants.DYNAMIC_KEY, true)) {
         try {
           unregister(url);
           if (logger.isInfoEnabled()) {
             logger.info("Destroy unregister url " + url);
           }
         } catch (Throwable t) {
           logger.warn(
               "Failed to unregister url "
                   + url
                   + " to registry "
                   + getUrl()
                   + " on destroy, cause: "
                   + t.getMessage(),
               t);
         }
       }
     }
   }
   Map<URL, Set<NotifyListener>> destroySubscribed =
       new HashMap<URL, Set<NotifyListener>>(getSubscribed());
   if (!destroySubscribed.isEmpty()) {
     for (Map.Entry<URL, Set<NotifyListener>> entry : destroySubscribed.entrySet()) {
       URL url = entry.getKey();
       for (NotifyListener listener : entry.getValue()) {
         try {
           unsubscribe(url, listener);
           if (logger.isInfoEnabled()) {
             logger.info("Destroy unsubscribe url " + url);
           }
         } catch (Throwable t) {
           logger.warn(
               "Failed to unsubscribe url "
                   + url
                   + " to registry "
                   + getUrl()
                   + " on destroy, cause: "
                   + t.getMessage(),
               t);
         }
       }
     }
   }
 }
예제 #3
0
  protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header)
      throws IOException {
    // check magic number.
    if (readable > 0 && header[0] != MAGIC_HIGH || readable > 1 && header[1] != MAGIC_LOW) {
      int length = header.length;
      if (header.length < readable) {
        header = Bytes.copyOf(header, readable);
        buffer.readBytes(header, length, readable - length);
      }
      for (int i = 1; i < header.length - 1; i++) {
        if (header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW) {
          buffer.readerIndex(buffer.readerIndex() - header.length + i);
          header = Bytes.copyOf(header, i);
          break;
        }
      }
      return super.decode(channel, buffer, readable, header);
    }
    // check length.
    if (readable < HEADER_LENGTH) {
      return DecodeResult.NEED_MORE_INPUT;
    }

    // get data length.
    int len = Bytes.bytes2int(header, 12);
    checkPayload(channel, len);

    int tt = len + HEADER_LENGTH;
    if (readable < tt) {
      return DecodeResult.NEED_MORE_INPUT;
    }

    // limit input stream.
    ChannelBufferInputStream is = new ChannelBufferInputStream(buffer, len);

    try {
      return decodeBody(channel, is, header);
    } finally {
      if (is.available() > 0) {
        try {
          if (logger.isWarnEnabled()) {
            logger.warn("Skip input stream " + is.available());
          }
          StreamUtils.skipUnusedStream(is);
        } catch (IOException e) {
          logger.warn(e.getMessage(), e);
        }
      }
    }
  }
예제 #4
0
  private void saveProperties(URL url) {
    if (file == null) {
      return;
    }

    try {
      StringBuilder buf = new StringBuilder();
      Map<String, List<URL>> categoryNotified = notified.get(url);
      if (categoryNotified != null) {
        for (List<URL> us : categoryNotified.values()) {
          for (URL u : us) {
            if (buf.length() > 0) {
              buf.append(URL_SEPARATOR);
            }
            buf.append(u.toFullString());
          }
        }
      }
      properties.setProperty(url.getServiceKey(), buf.toString());
      long version = lastCacheChanged.incrementAndGet();
      if (syncSaveFile) {
        doSaveProperties(version);
      } else {
        registryCacheExecutor.execute(new SaveProperties(version));
      }
    } catch (Throwable t) {
      logger.warn(t.getMessage(), t);
    }
  }
 private void deferExpired() {
   for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) {
     JedisPool jedisPool = entry.getValue();
     try {
       Jedis jedis = jedisPool.getResource();
       try {
         RedisRegistryUtil.publishToJedis(jedis, getRegistered(), root, expirePeriod);
         if (admin) {
           clean(jedis);
         }
         if (!replicate) {
           break; //  如果服务器端已同步数据,只需写入单台机器
         }
       } finally {
         jedisPool.returnResource(jedis);
       }
     } catch (Throwable t) {
       logger.warn(
           "Failed to write provider heartbeat to redis registry. registry: "
               + entry.getKey()
               + ", cause: "
               + t.getMessage(),
           t);
     }
   }
 }
 public void doSubscribe(final URL url, final NotifyListener listener) {
   String service = RedisRegistryUtil.toServicePath(url, root);
   RedisRegistryNotifier notifier = notifiers.get(service);
   if (notifier == null) {
     RedisRegistryNotifier newNotifier = new RedisRegistryNotifier(service, this);
     notifiers.putIfAbsent(service, newNotifier);
     notifier = notifiers.get(service);
     if (notifier == newNotifier) {
       notifier.start();
     }
   }
   boolean success = false;
   RpcException exception = null;
   for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) {
     JedisPool jedisPool = entry.getValue();
     try {
       Jedis jedis = jedisPool.getResource();
       try {
         if (service.endsWith(Constants.ANY_VALUE)) {
           admin = true;
           Set<String> keys = jedis.keys(service);
           if (keys != null && keys.size() > 0) {
             Map<String, Set<String>> serviceKeys = RedisRegistryUtil.getServiceKeys(keys, root);
             for (Set<String> sk : serviceKeys.values()) {
               doNotify(jedis, sk, url, Arrays.asList(listener));
             }
           }
         } else {
           doNotify(
               jedis,
               jedis.keys(service + Constants.PATH_SEPARATOR + Constants.ANY_VALUE),
               url,
               Arrays.asList(listener));
         }
         success = true;
         break; // 只需读一个服务器的数据
       } finally {
         jedisPool.returnResource(jedis);
       }
     } catch (Throwable t) { // 尝试下一个服务器
       exception =
           new RpcException(
               "Failed to subscribe service from redis registry. registry: "
                   + entry.getKey()
                   + ", service: "
                   + url
                   + ", cause: "
                   + t.getMessage(),
               t);
     }
   }
   if (exception != null) {
     if (success) {
       logger.warn(exception.getMessage(), exception);
     } else {
       throw exception;
     }
   }
 }
예제 #7
0
  public static void warn(Logger logger, Throwable e) {
    if (logger == null) {
      return;
    }

    if (logger.isWarnEnabled()) {
      logger.warn(e);
    }
  }
예제 #8
0
  public static void warn(Logger logger, String msg) {
    if (logger == null) {
      return;
    }

    if (logger.isWarnEnabled()) {
      logger.warn(msg);
    }
  }
 public void close() {
   try {
     if (executor instanceof ExecutorService) {
       ((ExecutorService) executor).shutdown();
     }
   } catch (Throwable t) {
     logger.warn("fail to destroy thread pool of server: " + t.getMessage(), t);
   }
 }
 @Override
 protected void doClose() throws Throwable {
   try {
     if (acceptor != null) {
       acceptor.unbind(getBindAddress());
     }
   } catch (Throwable e) {
     logger.warn(e.getMessage(), e);
   }
 }
예제 #11
0
 private void loadProperties() {
   if (file != null && file.exists()) {
     InputStream in = null;
     try {
       in = new FileInputStream(file);
       properties.load(in);
       if (logger.isInfoEnabled()) {
         logger.info("Load registry store file " + file + ", data: " + properties);
       }
     } catch (Throwable e) {
       logger.warn("Failed to load registry store file " + file, e);
     } finally {
       if (in != null) {
         try {
           in.close();
         } catch (IOException e) {
           logger.warn(e.getMessage(), e);
         }
       }
     }
   }
 }
예제 #12
0
 protected void notify(URL url, NotifyListener listener, List<URL> urls) {
   if (url == null) {
     throw new IllegalArgumentException("notify url == null");
   }
   if (listener == null) {
     throw new IllegalArgumentException("notify listener == null");
   }
   if ((urls == null || urls.size() == 0)
       && !Constants.ANY_VALUE.equals(url.getServiceInterface())) {
     logger.warn("Ignore empty notify urls for subscribe url " + url);
     return;
   }
   if (logger.isInfoEnabled()) {
     logger.info("Notify urls for subscribe url " + url + ", urls: " + urls);
   }
   Map<String, List<URL>> result = new HashMap<String, List<URL>>();
   for (URL u : urls) {
     if (UrlUtils.isMatch(url, u)) {
       String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
       List<URL> categoryList = result.get(category);
       if (categoryList == null) {
         categoryList = new ArrayList<URL>();
         result.put(category, categoryList);
       }
       categoryList.add(u);
     }
   }
   if (result.size() == 0) {
     return;
   }
   Map<String, List<URL>> categoryNotified = notified.get(url);
   if (categoryNotified == null) {
     notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>());
     categoryNotified = notified.get(url);
   }
   for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
     String category = entry.getKey();
     List<URL> categoryList = entry.getValue();
     categoryNotified.put(category, categoryList);
     saveProperties(url);
     listener.notify(categoryList);
   }
 }
  private void doNotify(
      Jedis jedis, Collection<String> keys, URL url, Collection<NotifyListener> listeners) {
    if (keys == null || keys.size() == 0 || listeners == null || listeners.size() == 0) {
      return;
    }
    long now = System.currentTimeMillis();
    List<URL> result = new ArrayList<URL>();
    List<String> categories =
        Arrays.asList(url.getParameter(Constants.CATEGORY_KEY, new String[0]));
    String consumerService = url.getServiceInterface();
    for (String key : keys) {
      if (!Constants.ANY_VALUE.equals(consumerService)) {
        String prvoiderService = RedisRegistryUtil.toServiceName(key, root);
        if (!prvoiderService.equals(consumerService)) {
          continue;
        }
      }
      String category = RedisRegistryUtil.toCategoryName(key);
      if (!categories.contains(Constants.ANY_VALUE) && !categories.contains(category)) {
        continue;
      }

      Map<String, String> values = jedis.hgetAll(key);
      List<URL> urls = RedisRegistryUtil.getUrlsForDoNotify(url, now, values);

      if (urls.isEmpty()) {
        urls.add(RedisRegistryUtil.setUrlProperties(url, key, category, root));
      }
      result.addAll(urls);
      if (logger.isWarnEnabled()) {
        logger.warn("redis notify: " + key + " = " + urls);
      }
    }
    if (result == null || result.size() == 0) {
      return;
    }
    for (NotifyListener listener : listeners) {
      notify(url, listener, result);
    }
  }
 public void doRegister(URL url) {
   String key = RedisRegistryUtil.toCategoryPath(url, root);
   String value = url.toFullString();
   String expire = String.valueOf(System.currentTimeMillis() + expirePeriod);
   boolean success = false;
   RpcException exception = null;
   for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) {
     JedisPool jedisPool = entry.getValue();
     try {
       Jedis jedis = jedisPool.getResource();
       try {
         jedis.hset(key, value, expire);
         jedis.publish(key, Constants.REGISTER);
         success = true;
         if (!replicate) {
           break; //  如果服务器端已同步数据,只需写入单台机器
         }
       } finally {
         jedisPool.returnResource(jedis);
       }
     } catch (Throwable t) {
       exception =
           new RpcException(
               "Failed to register service to redis registry. registry: "
                   + entry.getKey()
                   + ", service: "
                   + url
                   + ", cause: "
                   + t.getMessage(),
               t);
     }
   }
   if (exception != null) {
     if (success) {
       logger.warn(exception.getMessage(), exception);
     } else {
       throw exception;
     }
   }
 }
예제 #15
0
 public void doSaveProperties(long version) {
   if (version < lastCacheChanged.get()) {
     return;
   }
   if (file == null) {
     return;
   }
   Properties newProperties = new Properties();
   // 保存之前先读取一遍,防止多个注册中心之间冲突
   InputStream in = null;
   try {
     if (file.exists()) {
       in = new FileInputStream(file);
       newProperties.load(in);
     }
   } catch (Throwable e) {
     logger.warn("Failed to load registry store file, cause: " + e.getMessage(), e);
   } finally {
     if (in != null) {
       try {
         in.close();
       } catch (IOException e) {
         logger.warn(e.getMessage(), e);
       }
     }
   }
   // 保存
   try {
     newProperties.putAll(properties);
     File lockfile = new File(file.getAbsolutePath() + ".lock");
     if (!lockfile.exists()) {
       lockfile.createNewFile();
     }
     RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
     try {
       FileChannel channel = raf.getChannel();
       try {
         FileLock lock = channel.tryLock();
         if (lock == null) {
           throw new IOException(
               "Can not lock the registry cache file "
                   + file.getAbsolutePath()
                   + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");
         }
         // 保存
         try {
           if (!file.exists()) {
             file.createNewFile();
           }
           FileOutputStream outputFile = new FileOutputStream(file);
           try {
             newProperties.store(outputFile, "Dubbo Registry Cache");
           } finally {
             outputFile.close();
           }
         } finally {
           lock.release();
         }
       } finally {
         channel.close();
       }
     } finally {
       raf.close();
     }
   } catch (Throwable e) {
     if (version < lastCacheChanged.get()) {
       return;
     } else {
       registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
     }
     logger.warn("Failed to save registry store file, cause: " + e.getMessage(), e);
   }
 }
예제 #16
0
  public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    String generic = invoker.getUrl().getParameter(Constants.GENERIC_KEY);
    if (ProtocolUtils.isGeneric(generic)
        && !Constants.$INVOKE.equals(invocation.getMethodName())
        && invocation instanceof RpcInvocation) {
      RpcInvocation invocation2 = (RpcInvocation) invocation;
      String methodName = invocation2.getMethodName();
      Class<?>[] parameterTypes = invocation2.getParameterTypes();
      Object[] arguments = invocation2.getArguments();

      String[] types = new String[parameterTypes.length];
      for (int i = 0; i < parameterTypes.length; i++) {
        types[i] = ReflectUtils.getName(parameterTypes[i]);
      }
      Object[] args = PojoUtils.generalize(arguments);

      invocation2.setMethodName(Constants.$INVOKE);
      invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
      invocation2.setArguments(new Object[] {methodName, types, args});
      Result result = invoker.invoke(invocation2);

      if (!result.hasException()) {
        Object value = result.getValue();
        try {
          Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
          return new RpcResult(
              PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
        } catch (NoSuchMethodException e) {
          throw new RpcException(e.getMessage(), e);
        }
      } else if (result.getException() instanceof GenericException) {
        GenericException exception = (GenericException) result.getException();
        try {
          String className = exception.getExceptionClass();
          Class<?> clazz = ReflectUtils.forName(className);
          Throwable targetException = null;
          Throwable lastException = null;
          try {
            targetException = (Throwable) clazz.newInstance();
          } catch (Throwable e) {
            lastException = e;
            for (Constructor<?> constructor : clazz.getConstructors()) {
              try {
                targetException =
                    (Throwable)
                        constructor.newInstance(new Object[constructor.getParameterTypes().length]);
                break;
              } catch (Throwable e1) {
                lastException = e1;
              }
            }
          }
          if (targetException != null) {
            try {
              Field field = Throwable.class.getDeclaredField("detailMessage");
              if (!field.isAccessible()) {
                field.setAccessible(true);
              }
              field.set(targetException, exception.getExceptionMessage());
            } catch (Throwable e) {
              logger.warn(e.getMessage(), e);
            }
            result = new RpcResult(targetException);
          } else if (lastException != null) {
            throw lastException;
          }
        } catch (Throwable e) {
          throw new RpcException(
              "Can not deserialize exception "
                  + exception.getExceptionClass()
                  + ", message: "
                  + exception.getExceptionMessage(),
              e);
        }
      }
      return result;
    }

    if (invocation.getMethodName().equals(Constants.$INVOKE)
        && invocation.getArguments() != null
        && invocation.getArguments().length == 3
        && ProtocolUtils.isGeneric(generic)) {

      if (ProtocolUtils.isJavaGenericSerialization(generic)) {
        Object[] args = (Object[]) invocation.getArguments()[2];

        for (Object arg : args) {
          if (!(byte[].class == arg.getClass())) {
            error(arg.getClass().getName());
          }
        }
      }

      ((RpcInvocation) invocation)
          .setAttachment(
              Constants.GENERIC_KEY, invoker.getUrl().getParameter(Constants.GENERIC_KEY));
    }
    return invoker.invoke(invocation);
  }
예제 #17
0
  protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res)
      throws IOException {
    try {
      Serialization serialization = getSerialization(channel);
      // header.
      byte[] header = new byte[HEADER_LENGTH];
      // set magic number.
      Bytes.short2bytes(MAGIC, header);
      // set request and serialization flag.
      header[2] = serialization.getContentTypeId();
      if (res.isHeartbeat()) header[2] |= FLAG_EVENT;
      // set response status.
      byte status = res.getStatus();
      header[3] = status;
      // set request id.
      Bytes.long2bytes(res.getId(), header, 4);

      int savedWriteIndex = buffer.writerIndex();
      buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
      ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
      ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
      try {
        // encode response data or error message.
        if (status == Response.OK) {
          if (res.isHeartbeat()) {
            encodeHeartbeatData(channel, out, res.getResult());
          } else {
            encodeResponseData(channel, out, res.getResult());
          }
        } else out.writeUTF(res.getErrorMessage());
        out.flushBuffer();
      } finally {
        // modified by lishen
        if (out instanceof Cleanable) {
          ((Cleanable) out).cleanup();
        }
      }

      bos.flush();
      bos.close();

      int len = bos.writtenBytes();
      checkPayload(channel, len);
      Bytes.int2bytes(len, header, 12);
      // write
      buffer.writerIndex(savedWriteIndex);
      buffer.writeBytes(header); // write header.
      buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
    } catch (Throwable t) {
      // 发送失败信息给Consumer,否则Consumer只能等超时了
      if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) {
        try {
          // FIXME 在Codec中打印出错日志?在IoHanndler的caught中统一处理?
          logger.warn(
              "Fail to encode response: "
                  + res
                  + ", send bad_response info instead, cause: "
                  + t.getMessage(),
              t);

          Response r = new Response(res.getId(), res.getVersion());
          r.setStatus(Response.BAD_RESPONSE);
          r.setErrorMessage(
              "Failed to send response: " + res + ", cause: " + StringUtils.toString(t));
          channel.send(r);

          return;
        } catch (RemotingException e) {
          logger.warn(
              "Failed to send bad_response info back: " + res + ", cause: " + e.getMessage(), e);
        }
      }

      // 重新抛出收到的异常
      if (t instanceof IOException) {
        throw (IOException) t;
      } else if (t instanceof RuntimeException) {
        throw (RuntimeException) t;
      } else if (t instanceof Error) {
        throw (Error) t;
      } else {
        throw new RuntimeException(t.getMessage(), t);
      }
    }
  }