【源码系列-4】【fastdfs系列-1】初始化客户端

【fastdfs系列一】初始化客户端

    • 解析配置文件、创建tracker group
    • 获取tracker

事前声明

  • 本文使用的是100只(Mr / Miss)快乐鱼的开源代码,附上源码链接:https://github.com/happyfish100/

从一个测试用例入手分析,若想对fastdfs中的文件进行操作,首先需要初始化客户端,初始化的过程分为下面几步:

  1. 解析配置文件
  2. 根据配置文件中的数据生成tracker server group实例(点我查看详情)
  3. 与一个tracker server连接
  4. 根据tracker server和 storage server生成storage client实例,该实例可对文件进行上传、下载、删除等操作。
 @Before
    public void initStorageClient() throws Exception {
    	// init 函数中实现了前面提到的前两步。
        ClientGlobal.init(CONF_NAME);
        LOGGER.info("network_timeout=" + ClientGlobal.g_network_timeout + "ms");
        LOGGER.info("charset=" + ClientGlobal.g_charset);
        // 创建TrackerClient对象就是把在init中创建的,且已经赋值给ClientGlobal的g_tracker_group成员变量的值赋值给TrackerClient的tracker_group成员变量。
        /**
        * public TrackerClient() {
        *     this.tracker_group = ClientGlobal.g_tracker_group;
        * }
        */
        TrackerClient tracker = new TrackerClient();
        // TrackerClient的getTrackerServer方法还是直接调用的TrackerGroup的方法(点我去看看这个方法多牛逼),总之就是给你选了个合适的tracker server让你连上了。
        trackerServer = tracker.getTrackerServer();
        StorageServer storageServer = null;
        // 实例化StorageClient
        storageClient = new StorageClient(trackerServer, storageServer);
    }

解析配置文件、创建tracker group

init函数在ClienGlobal类中,该类中定义了一些列的静态常量。其中涉及到TrackerGroup对象,该
对象生成了tracker group,老厉害了,等看到这块不明白,记得返回来点跳转。

public static void init(String conf_filename) throws IOException, MyException {
    IniFileReader iniReader;
    // 一个fastdns中,有多个tracker,因此这里用数组保存。
    String[] szTrackerServers;
    String[] parts;

	// 把配置文件中的内容读到HashTable中,IniFileReader类有两个成员变量,分别为这个HashTable和配置文件名称。
    iniReader = new IniFileReader(conf_filename);
	//赋值连接超时
    g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT);
    if (g_connect_timeout < 0) {
      g_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
    }
    g_connect_timeout *= 1000; //millisecond
	//赋值网络超时
    g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT);
    if (g_network_timeout < 0) {
      g_network_timeout = DEFAULT_NETWORK_TIMEOUT;
    }
    g_network_timeout *= 1000; //millisecond
	//赋值字符集
    g_charset = iniReader.getStrValue("charset");
    if (g_charset == null || g_charset.length() == 0) {
      g_charset = "ISO8859-1";
    }
	
    szTrackerServers = iniReader.getValues("tracker_server");
    if (szTrackerServers == null) {
      throw new MyException("item \"tracker_server\" in " + conf_filename + " not found");
    }

    // 将配置文件中的tracker server信息转换为InetSocketAddress类,InetSocketAddress是java内置类,有成员变量hostname、 addr、port;
    InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
    for (int i = 0; i < szTrackerServers.length; i++) {
      parts = szTrackerServers[i].split("\\:", 2);
      if (parts.length != 2) {
        throw new MyException("the value of item \"tracker_server\" is invalid, the correct format is host:port");
      }

      tracker_servers[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim()));
    }
    // 把生成的tracker server注册到g_tracker_group,这里是生成了一个TrackerGroup对象,这个对象厉害了,下面会讲。
    g_tracker_group = new TrackerGroup(tracker_servers);
	//下面的这些g开头的都是ClientGlobal里的静态成员变量,都是读配置文件里面的信息。
    g_tracker_http_port = iniReader.getIntValue("http.tracker_http_port", 80);
    g_anti_steal_token = iniReader.getBoolValue("http.anti_steal_token", false);
    if (g_anti_steal_token) {
      g_secret_key = iniReader.getStrValue("http.secret_key");
    }
    g_connection_pool_enabled = iniReader.getBoolValue("connection_pool.enabled", DEFAULT_CONNECTION_POOL_ENABLED);
    g_connection_pool_max_count_per_entry = iniReader.getIntValue("connection_pool.max_count_per_entry", DEFAULT_CONNECTION_POOL_MAX_COUNT_PER_ENTRY);
    g_connection_pool_max_idle_time = iniReader.getIntValue("connection_pool.max_idle_time", DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME);
    if (g_connection_pool_max_idle_time < 0) {
      g_connection_pool_max_idle_time = DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME;
    }
    g_connection_pool_max_idle_time *= 1000;
    g_connection_pool_max_wait_time_in_ms = iniReader.getIntValue("connection_pool.max_wait_time_in_ms", DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS);
    if (g_connection_pool_max_wait_time_in_ms < 0) {
      g_connection_pool_max_wait_time_in_ms = DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS;
    }
  }

获取tracker

前面把TrackerGroup对象赋值给g_tracker_group,看看这个类干了些什么:

首先,他有3个成员变量

public int tracker_server_index;
public InetSocketAddress[] tracker_servers;
protected Integer lock;

他主要提供两个get tracker server的方法

  1. 根据index获取
public TrackerServer getTrackerServer(int serverIndex) throws IOException {
    return new TrackerServer(this.tracker_servers[serverIndex]);
  }
  1. 获取当前连接的server的后面一个server
    同步获取index,避免因为对象修改index导致返回已经连接的server导致并发问题。如果连接该tracker server失败,则遍历所有server,尝试连接除上述失败的server以外的server,知道连接成功,如果都失败了,那您好好看看端口,ip,以及部署的fastdfs吧。
public TrackerServer getTrackerServer() throws IOException {
    int current_index;

    synchronized (this.lock) {
      this.tracker_server_index++;
      if (this.tracker_server_index >= this.tracker_servers.length) {
        this.tracker_server_index = 0;
      }

      current_index = this.tracker_server_index;
    }

    try {
      return this.getTrackerServer(current_index);
    } catch (IOException ex) {
      System.err.println("connect to server " + this.tracker_servers[current_index].getAddress().getHostAddress() + ":" + this.tracker_servers[current_index].getPort() + " fail");
      ex.printStackTrace(System.err);
    }

    for (int i = 0; i < this.tracker_servers.length; i++) {
      if (i == current_index) {
        continue;
      }

      try {
        TrackerServer trackerServer = this.getTrackerServer(i);

        synchronized (this.lock) {
          if (this.tracker_server_index == current_index) {
            this.tracker_server_index = i;
          }
        }

        return trackerServer;
      } catch (IOException ex) {
        System.err.println("connect to server " + this.tracker_servers[i].getAddress().getHostAddress() + ":" + this.tracker_servers[i].getPort() + " fail");
        ex.printStackTrace(System.err);
      }
    }

    return null;

你可能感兴趣的:(源码)