C/C++编程:连接池服务管理类connect_manager用来管理 connectpool

╰半橙微兮° 2022-09-04 03:00 192阅读 0赞

版本1:每个连接管理类都必须创建一个连接池对象

这时可以通过指定子类必须实现 create_pool,用来创建子类所要管理的连接池对象

  1. #ifndef OCEANSTAR_HTTP_CONNECT_MANAGER_H
  2. #define OCEANSTAR_HTTP_CONNECT_MANAGER_H
  3. #include <noncopyable.h>
  4. #include "connect_pool.h"
  5. namespace oceanstar{
  6. /**
  7. * connect pool 服务管理器,有获取连接池等功能
  8. */
  9. class connect_manager : public noncopyable{
  10. protected:
  11. /**
  12. * 纯虚函数,子类必须实现此函数用来创建连接池对象
  13. * @param addr {const char*} 服务器监听地址,格式:ip:port
  14. * @param count {size_t} 连接池的大小限制,为 0 时,则连接池没有限制
  15. * @return {connect_pool*} 返回创建的连接池对象
  16. */
  17. virtual connect_pool* create_pool(const char* addr, size_t count) = 0;
  18. };
  19. }
  20. #endif //OCEANSTAR_HTTP_CONNECT_MANAGER_H
  21. class connect_manager : public oceanstar::connect_manager
  22. {
  23. public:
  24. connect_manager(){
  25. }
  26. virtual ~connect_manager(){
  27. }
  28. protected:
  29. // 基类纯虚函数的实现
  30. oceanstar::connect_pool* create_pool(const char* addr,size_t count){
  31. return new connect_pool(addr, count);
  32. }
  33. };

功能:根据服务端地址获得或者创建该服务器的连接池

  1. /**
  2. * 根据服务端地址获得该服务器的连接池
  3. * @param addr {const char*} redis 服务器地址(ip:port)
  4. * @param exclusive {bool} 是否需要互斥访问连接池数组,当需要动态
  5. * 管理连接池集群时,该值应为 true
  6. * @param restore {bool} 当该服务结点被置为不可用时,该参数决定是否
  7. * 自动将之恢复为可用状态
  8. * @return {connect_pool*} 返回空表示没有此服务
  9. */
  10. connect_pool* connect_manager::get(const char* addr, bool exclusive /* = true */, bool restore /* = false */){
  11. std::string key;
  12. get_key(addr, key);
  13. unsigned long id = get_id();
  14. if (exclusive) {
  15. lock_.lock();
  16. }
  17. conns_pools& pools = get_pools_by_id(id); // 去manager_中找,如果conns_pools已经创建就直接返回,如果没有创建就新创建一个(connect_manager中可以管理多个conns_pools)
  18. // 如果当前conns_pools中某个connect_pool的addr与当前addr相同,就返回
  19. pools_t::iterator it = pools.pools.begin();
  20. for (; it != pools.pools.end(); ++it) {
  21. if (key == (*it)->get_key()) {
  22. if (restore && (*it)->aliving() == false) {
  23. (*it)->set_alive(true);
  24. }
  25. if (exclusive) {
  26. lock_.unlock();
  27. }
  28. return *it;
  29. }
  30. }
  31. std::map<string, conn_config>::const_iterator cit = addrs_.find(key);
  32. if (cit == addrs_.end()) {
  33. if (exclusive) {
  34. lock_.unlock();
  35. }
  36. logger_error( "no connect pool for addr %s", addr);
  37. return NULL;
  38. }
  39. conn_config config = cit->second;
  40. connect_pool* pool = create_pool(config); // 根据当前addr的配置来创建一个连接池
  41. pools.pools.push_back(pool); //将当前连接池压入被管理的数组中
  42. if (exclusive) {
  43. lock_.unlock();
  44. }
  45. return pool;
  46. }

功能:初始化服务器集群(所有服务器的连接池)

  1. /**
  2. * 添加服务器的客户端连接池,该函数可以在程序运行时被调用,内部自动加锁
  3. * @param addr {const char*} 服务器地址,格式:ip:port
  4. * 注意:调用本函数时每次仅能添加一个服务器地址,可以循环调用本方法
  5. * @param count {size_t} 连接池数量限制, 如果该值设为 0,则不设置
  6. * 连接池的连接上限
  7. * @param conn_timeout {int} 网络连接时间(秒)
  8. * @param rw_timeout {int} 网络 IO 超时时间(秒)
  9. */
  10. void connect_manager::set(const char *addr, size_t count, int conn_timeout /* = 30 */, int rw_timeout /* = 30 */) {
  11. std::string buf(addr);
  12. boost::to_lower(buf);
  13. thread_mutex_guard guard(lock_);
  14. std::map<std::string, conn_config>::iterator it = addrs_.find(buf);
  15. if (it == addrs_.end()) {
  16. conn_config config;
  17. config.addr = addr;
  18. config.count = count;
  19. config.conn_timeout = conn_timeout;
  20. config.rw_timeout = rw_timeout;
  21. addrs_[buf] = config;
  22. } else {
  23. it->second.count = count;
  24. it->second.conn_timeout = conn_timeout;
  25. it->second.rw_timeout = rw_timeout;
  26. }
  27. }
  28. // 分析一个服务器地址,格式:IP:PORT[:MAX_CONN]
  29. // 返回值 < 0 表示非法的地址
  30. static int check_addr(const char* addr, std::string& buf, size_t default_count){
  31. // 数据格式:IP:PORT[:CONNECT_COUNT]
  32. ACL_ARGV* tokens = acl_argv_split(addr, ":");
  33. if (tokens->argc < 2) {
  34. logger_error("invalid addr: %s", addr);
  35. acl_argv_free(tokens);
  36. return -1;
  37. }
  38. int port = atoi(tokens->argv[1].c_str());
  39. if (port <= 0 || port >= 65535) {
  40. logger_error("invalid addr: %s, port: %d", addr, port);
  41. acl_argv_free(tokens);
  42. return -1;
  43. }
  44. buf = format("%s:%d", tokens->argv[0].c_str(), port);
  45. int conn_max;
  46. if (tokens->argc >= 3) {
  47. conn_max = atoi(tokens->argv[2].c_str());
  48. } else {
  49. conn_max = (int) default_count;
  50. }
  51. if (conn_max < 0) {
  52. conn_max = (int) default_count;
  53. }
  54. acl_argv_free(tokens);
  55. return conn_max;
  56. }
  57. // 设置除缺省服务之外的服务器集群
  58. void connect_manager::set_service_list(const char* addr_list, int count, int conn_timeout, int rw_timeout){
  59. if (addr_list == NULL || *addr_list == 0) {
  60. logger_warn("addr_list null");
  61. return;
  62. }
  63. // 创建连接池服务集群
  64. char *buf = strdup(addr_list);
  65. char* addrs = acl_mystr_trim(buf);
  66. ACL_ARGV* tokens = acl_argv_split(addrs, ";");
  67. std::string addr;
  68. for(const auto& iter : tokens->argv){
  69. const char* ptr = iter.c_str();
  70. int max = check_addr(ptr, addr, count); // addr = [ptr列表中的第一个 (ip:port)]
  71. if (max < 0) {
  72. logger_error("invalid server addr: %s", addr.c_str());
  73. continue;
  74. }
  75. set(addr.c_str(), max, conn_timeout, rw_timeout); // 设置addrs
  76. logger_info("add one service: %s, max connect: %d", addr.c_str(), max);
  77. }
  78. acl_argv_free(tokens);
  79. free(buf);
  80. }
  81. /**
  82. * 初始化所有服务器的连接池,该函数调用 set 过程添加每个服务的连接池
  83. * @param default_addr {const char*} 缺省的服务器地址,如果非空,
  84. * 则在查询时优先使用此服务器
  85. * @param addr_list {const char*} 所有服务器列表,可以为空
  86. * 格式: IP:PORT:COUNT;IP:PORT:COUNT;IP:PORT;IP:PORT ...
  87. * 或 IP:PORT:COUNT,IP:PORT:COUNT,IP:PORT;IP:PORT ...
  88. * 如:127.0.0.1:7777:50;192.168.1.1:7777:10;127.0.0.1:7778
  89. * @param count {size_t} 当 addr_list 中分隔的某个服务没有
  90. * COUNT 信息时便用此值,当此值为 0 时,则不限制连接数上限
  91. * @param conn_timeout {int} 网络连接时间(秒)
  92. * @param rw_timeout {int} 网络 IO 超时时间(秒)
  93. * 注:default_addr 和 addr_list 不能同时为空
  94. */
  95. void connect_manager::init(const char* default_addr, const char* addr_list,
  96. size_t count, int conn_timeout /* = 30 */, int rw_timeout /* = 30 */ ){
  97. if (addr_list != NULL && *addr_list != 0) {
  98. set_service_list(addr_list, (int) count, conn_timeout, rw_timeout); // 设置 addrs_: 如果在addrs找不到addr就插入并配置配置,如果找得到就更新配置
  99. }
  100. // 创建缺省服务连接池对象,该对象一同放入总的连接池集群中
  101. if (default_addr != NULL && *default_addr != 0) {
  102. logger_info("default_pool: %s", default_addr);
  103. int max = check_addr(default_addr, default_addr_, count); // 设置default_addr_ : 设置default_addr_ = [default_addr列表中的第一个 (ip:port)]
  104. if (max < 0) {
  105. logger_info("no default connection set");
  106. } else {
  107. set(default_addr_.c_str(), max, conn_timeout, rw_timeout); //设置default_addr_的配置
  108. default_pool_ = get(default_addr_.c_str()); //将当前default_addr_绑定到一个连接池上
  109. }
  110. } else {
  111. logger_info("no default connection set");
  112. }
  113. }

发表评论

表情:
评论列表 (有 0 条评论,192人围观)

还没有评论,来说两句吧...

相关阅读