源码走读rgw内置civetweb的参数初始化过程

时间:2022-04-25
本文章向大家介绍源码走读rgw内置civetweb的参数初始化过程,主要内容包括2. rgw中对civetweb启动时的参数初始化、3. 几个比较有用的参数介绍、access_control_list、num_threads、allow_sendfile_call、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

1. 初始化civetweb时刻的参数传递

src/civetweb/civetweb.h

/* Start web server.

   Parameters:
     callbacks: mg_callbacks structure with user-defined callbacks.
     options: NULL terminated list of option_name, option_value pairs that
              specify Civetweb configuration parameters.

   Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
      processing is required for these, signal handlers must be set up
      after calling mg_start().


   Example:
     const char *options[] = {
       "document_root", "/var/www",
       "listening_ports", "80,443s",
       NULL
     };
     struct mg_context *ctx = mg_start(&my_func, NULL, options);

   Refer to https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md
   for the list of valid option and their possible values.

   Return:
     web server context, or NULL on error. */
CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks,
                            void *user_data,
                            const char **configuration_options);

civetweb启动时的参数初始化由mg_start函数实现,注意configuration_options为具体的配置参数,配置参数的介绍可以参考https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md

2. rgw中对civetweb启动时的参数初始化

src/rgw/rgw_civetweb_frontend.cc

int RGWMongooseFrontend::run() {
  char thread_pool_buf[32];
  snprintf(thread_pool_buf, sizeof(thread_pool_buf), "%d",
       (int)g_conf->rgw_thread_pool_size);
  string port_str;
  map<string, string> conf_map = conf->get_config_map();
  conf->get_val("port", "80", &port_str);
  conf_map.erase("port");
  conf_map["listening_ports"] = port_str; #默认端口设置
  set_conf_default(conf_map, "enable_keep_alive", "yes"); #默认开启了keepalive
  set_conf_default(conf_map, "num_threads", thread_pool_buf); #从rgw_thread_pool_size这个配置项中读取对应的并发数
  set_conf_default(conf_map, "decode_url", "no");

  // Set run_as_user. This will cause civetweb to invoke setuid() and setgid()
  // based on pw_uid and pw_gid obtained from pw_name.
  string uid_string = g_ceph_context->get_set_uid_string();
  if (!uid_string.empty()) {
    conf_map.erase("run_as_user");
    conf_map["run_as_user"] = uid_string;
  }

  const char *options[conf_map.size() * 2 + 1];
  int i = 0;
  for (map<string, string>::iterator iter = conf_map.begin();
       iter != conf_map.end(); ++iter) {
    options[i] = iter->first.c_str();
    options[i + 1] = iter->second.c_str();
    dout(20)<< "civetweb config: " << options[i] << ": "
        << (options[i + 1] ? options[i + 1] : "<null>") << dendl;
    i += 2;
  }
  options[i] = NULL;

  struct mg_callbacks cb;
  memset((void *)&cb, 0, sizeof(cb));
  cb.begin_request = civetweb_callback;
  cb.log_message = rgw_civetweb_log_callback;
  cb.log_access = rgw_civetweb_log_access_callback;
  ctx = mg_start(&cb, &env, (const char **)&options);#启动civetweb

  if (!ctx) {
    return -EIO;
  }

  return 0;
} /* RGWMongooseFrontend::run */

通过RGWMongooseFrontend的run方法,实现了civetweb的启动参数初始化。

3. 几个比较有用的参数介绍

throttle

Limit download speed for clients. throttle is a comma-separated list of key=value pairs, where key could be:

*                   limit speed for all connections
x.x.x.x/mask        limit speed for specified subnet
uri_prefix_pattern  limit speed for given URIs

The value is a floating-point number of bytes per second, optionally followed by a k or m character, meaning kilobytes and megabytes respectively. A limit of 0 means unlimited rate. The last matching rule wins. Examples:

*=1k,10.0.0.0/8=0   limit all accesses to 1 kilobyte per second,
                    but give connections the from 10.0.0.0/8 subnet
                    unlimited speed

/downloads/=5k      limit accesses to all URIs in `/downloads/` to
                    5 kilobytes per second. All other accesses are unlimited

可以实现针对不同的subnet和URL设置下载速度,在需要限速的场景下比较有用

access_control_list

An Access Control List (ACL) allows restrictions to be put on the list of IP addresses which have access to the web server. In the case of the Civetweb web server, the ACL is a comma separated list of IP subnets, where each subnet is pre-pended by either a - or a + sign. A plus sign means allow, where a minus sign means deny. If a subnet mask is omitted, such as -1.2.3.4, this means to deny only that single IP address.

Subnet masks may vary from 0 to 32, inclusive. The default setting is to allow all accesses. On each request the full list is traversed, and the last match wins. Examples:

-0.0.0.0/0,+192.168/16    deny all accesses, only allow 192.168/16 subnet

这个应该都比较熟了,ACL控制哪些subnet或者host可以访问

num_threads

Number of worker threads. Civetweb handles each incoming connection in a separate thread. Therefore, the value of this option is effectively the number of concurrent HTTP connections Civetweb can handle.

控制单个civetweb实例的最大并发数

allow_sendfile_call

This option can be used to enable or disable the use of the Linux sendfile system call. It is only available for Linux systems and only affecting HTTP (not HTTPS) connections if throttle is not enabled. While using the sendfile call will lead to a performance boost for HTTP connections, this call may be broken for some file systems and some operating system versions.

援引一段对sendfile特性的描述 sendfile() copies data between one file descriptor and another.Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space. 启动该特性以后部分数据复制操作将在内核内部完成,能够减少上下文切换带来的性能损耗。

http://man7.org/linux/man-pages/man2/sendfile.2.html