예제 #1
0
/**
 * 黏包 (@see io.netty.handler.codec.LengthFieldBasedFrameDecoder)
 *
 * @author kim 2015年7月8日
 */
public enum CodecHeader {
  ONE,
  TWO,
  FOUR,
  EIGHT;

  /** 黏包字节自身长度 */
  private static final CodecHeader CODEC =
      CodecHeader.valueOf(
          PropertiesUtils.get(
              CodecHeader.class.getName().toLowerCase() + ".codec", CodecHeader.FOUR.toString()));

  private static final Map<CodecHeader, Integer> MAPPING = new HashMap<CodecHeader, Integer>();

  static {
    MAPPING.put(ONE, 1);
    MAPPING.put(TWO, 2);
    MAPPING.put(FOUR, 4);
    MAPPING.put(EIGHT, 8);
  }

  public static final int DEFAULT = CodecHeader.CODEC.code();

  public int code() {
    return MAPPING.get(this).intValue();
  }
}
예제 #2
0
/**
 * @author kim
 *     <p>2016年2月11日
 */
public interface SerialID {

  public static final String SERIAL_DEF = "default";

  public static final String SERIAL_KEY = SerialID.class.getName().toLowerCase() + ".serial";

  /** 默认序列化策略 */
  public static final String SERIAL_VAL =
      PropertiesUtils.get(SerialID.SERIAL_KEY, SerialID.SERIAL_DEF);

  /** 是否允许动态化序列化策略(Profile) */
  public static final boolean DYAMIC =
      PropertiesUtils.get(SerialID.class.getName().toLowerCase() + ".dynamic", false);

  /**
   * 获取序列化策略
   *
   * @return
   */
  @JsonProperty
  public byte serial();
}
예제 #3
0
/** @author kim 2015年7月9日 */
public class ZkContext implements Imported, Exported {

  public static final String ROOT =
      PropertiesUtils.get(Roadmap.class.getName().toLowerCase() + ".root", "/kepler");

  public static final boolean WATCH =
      Boolean.valueOf(
          PropertiesUtils.get(Roadmap.class.getName().toLowerCase() + ".watch", "true"));

  /** 单线程防止线程冲突 */
  private static final ExecutorService SERVICE = Executors.newFixedThreadPool(1);

  private static final Log LOGGER = LogFactory.getLog(ZkContext.class);

  private final AtomicBoolean shutdown = new AtomicBoolean();

  private final Runnable changed = new ChangedRunnable();

  private final Exporteds exported = new Exporteds();

  private final Importeds imported = new Importeds();

  private final Roadmap road = new Roadmap();

  private final RouteChanges changes;

  private final HostsContext context;

  private final SerialFactory serial;

  private final Connect connect;

  private final ZooKeeper zoo;

  private final Host local;

  public ZkContext(
      HostsContext context,
      RouteChanges changes,
      SerialFactory serial,
      Connect connect,
      ZooKeeper zoo,
      Host local) {
    super();
    this.zoo = zoo;
    this.local = local;
    this.serial = serial;
    this.changes = changes;
    this.context = context;
    this.connect = connect;
  }

  public void init() {
    ZkContext.SERVICE.execute(this.changed);
  }

  public void destory() throws Exception {
    this.exported.destory();
    this.shutdown.set(true);
    ZkContext.SERVICE.shutdown();
  }

  private void put(ZkSerial node, String path) throws Exception {
    // 加锁Service all version (粗粒度)
    synchronized (node.service()) {
      // 同步GetOrCreate
      this.context.get(node.service(), node.version()).put(node.host());
    }
    this.imported.put(path, node.host());
    this.connect.connect(node.host());
  }

  private void importing(String services) throws Exception {
    for (String each : this.zoo.getChildren(services, ZkContext.WATCH)) {
      try {
        String path = services + "/" + each;
        // 监听指定版本, 无需node.version(version)
        this.put(
            this.serial.serial(this.zoo.getData(path, ZkContext.WATCH, null), ZkSerial.class),
            path);
      } catch (Exception e) {
        e.printStackTrace();
        ZkContext.LOGGER.error(e.getMessage(), e);
      }
    }
  }

  @Override
  public void subscribe(Class<?> service, String version) throws Exception {
    for (String each :
        this.zoo.getChildren(
            this.road.roadmap(this.road.path(service, version)), ZkContext.WATCH)) {
      try {
        String path = this.road.path(service, version, each);
        ZkSerial node =
            this.serial.serial(this.zoo.getData(path, ZkContext.WATCH, null), ZkSerial.class);
        if (node.version(version)) {
          this.put(node, path);
        }
      } catch (Exception e) {
        e.printStackTrace();
        ZkContext.LOGGER.error(e.getMessage(), e);
      }
    }
  }

  @Override
  public void exported(Class<?> service, String version, Object instance) throws Exception {
    this.exported.put(
        this.zoo.create(
            this.road.roadmap(this.road.path(service, version)) + (ZkContext.ROOT + "_"),
            this.serial.serial(new ZkSerial(this.local, version, service)),
            Ids.OPEN_ACL_UNSAFE,
            CreateMode.EPHEMERAL_SEQUENTIAL));
  }

  private class Roadmap {

    public String path(Class<?> service, String... path) {
      StringBuffer buffer =
          new StringBuffer(ZkContext.ROOT)
              .append("/")
              .append(service.getName().replaceAll("\\.", "/"))
              .append("/");
      for (String each : path) {
        buffer.append(each).append("/");
      }
      return buffer.substring(0, buffer.length() - 1);
    }

    public String roadmap(String path) throws Exception {
      StringBuffer buffer = new StringBuffer();
      for (String each : path.split("/")) {
        if (StringUtils.hasText(each)) {
          String road = buffer.append("/").append(each).toString();
          if (ZkContext.this.zoo.exists(road, ZkContext.WATCH) == null) {
            ZkContext.this.zoo.create(
                road, new byte[] {}, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
          }
        }
      }
      return path;
    }
  }

  private class Exporteds {

    private final Set<String> exported = new CopyOnWriteArraySet<String>();

    public void put(String path) {
      this.exported.add(path);
    }

    public void destory() {
      for (String exported : this.exported) {
        try {
          ZkContext.this.zoo.delete(exported, 0);
        } catch (Exception e) {
          e.printStackTrace();
          ZkContext.LOGGER.error(e.getMessage(), e);
        }
      }
    }
  }

  private class Importeds {

    private final Map<String, Host> imported = new ConcurrentHashMap<String, Host>();

    public void put(String path, Host host) {
      this.imported.put(path, host);
    }

    public void destory(String path) {
      Host host = this.imported.remove(path);
      if (host != null) {
        ZkContext.this.context.del(host);
      }
    }
  }

  private class ChangedRunnable implements Runnable {
    @Override
    public void run() {
      while (!ZkContext.this.shutdown.get()) {
        try {
          RouteChange change = ZkContext.this.changes.get();
          switch (change.action()) {
            case PUSH:
              ZkContext.this.importing(change.route());
              continue;
            case DEL:
              ZkContext.this.imported.destory(change.route());
              continue;
          }
        } catch (Throwable e) {
          e.printStackTrace();

          ZkContext.LOGGER.error(e.getMessage(), e);
        }
      }
      ZkContext.LOGGER.warn(this.getClass() + " shutdown ...");
    }
  }
}