负载均衡权重系数算法 C++

为保证程序的稳定性和质量,内存要求使用智能指针(c++11),同时使用了boost(智能指针使用c++11)。
1 自定义标准头文件se_std.h

#ifndef H_CF4BC297_2737_4B2E_AB51_C0915F823960
#define H_CF4BC297_2737_4B2E_AB51_C0915F823960

#include <stdexcept>
#include <string>
#include <boost/exception/all.hpp>

/*检查指针参数是否有效*/
#define CHECK_PTRPARAM_ISNULL(x)\
do { \
    if(NULL == x) \
        SE_THROW("invalid parameter!"); \
} while (0)

/*检查智能指針是否成功,失败抛出异常*/
#define CHECK_SMART_PTR(x)\
do { \
    if(!x) \
        SE_THROW("out of memory!"); \
} while (0)

/*检查分配内存是否成功,失败抛出异常*/
#define CHECK_MALLOC_ISFAIL(x)\
do { \
    if(NULL == x) \
        SE_THROW("out of memory!"); \
} while (0)

/*检查并释放内存*/
#define CHECK_FREE(x)\
 do {\
    if(NULL != x) { \
        free(x); x = NULL; \
    } \
} while (0)

/*这个宏仅用于代码折叠*/
#define SE_COLLAPSE

/*自定义数据类型,使之在各个平台上都能符合要求*/
#define BYTE        unsigned char
#define INT2            short
#define UINT2       unsigned    short
#define INT4            int
#define UINT4       unsigned int
#define FLOAT4  float
#define FLOAT8  double
#if defined(_MSC_VER )
#define INT8            __int64
#define UINT8       unsigned __int64 INT8
#else
#define INT8            long long int
#define UINT8       unsigned long long int
#endif

/*
 * 自定义异常类和异常类型
 */
struct se_exception : virtual std::exception, virtual boost::exception {};
typedef boost::error_info<struct _tag_error_messsage_, std::string> se_error_message;
/*
 *  抛出异常(异常消息、文件名、行号、抛出异常的函数)
 *  获取异常消息:         std::string err_msg = *boost::get_error_info<se_error_message>(exp);
 *  获取文件名:          std::string file_name = *boost::get_error_info<boost::throw_file>(exp);
 *  获取行号:           int at_line = *boost::get_error_info<boost::throw_line>(exp);
 *  获取抛出异常的函数:  std::string str_api_function = *boost::get_error_info<boost::throw_function>(exp);
 */
#define SE_THROW(msg) throw se_exception()<<se_error_message(msg)\
    <<boost::throw_file(__FILE__)\
    <<boost::throw_line((int)__LINE__)\
    <<boost::throw_function(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION)

#endif /* H_CF4BC297_2737_4B2E_AB51_C0915F823960 */

2 平滑加权轮询算法se_balancing.hpp

/*============================================================================
Author          :   
Version         :   1.0
Copyright       :   
Description :   负载均衡,根据权重系数计算使用那台服务器,参考Nginx源码实现,平滑加权轮询(smooth weighted round-robin balancing)
                算法实现se_balancer::get_next_server_index                      
Create          :   2018-01-06
LastChange  :
============================================================================*/

#ifndef H_DC4C657C_63BF_450F_8AD5_42ADCBFF69A8
#define H_DC4C657C_63BF_450F_8AD5_42ADCBFF69A8

#include <string>
#include <vector>
#include <boost/noncopyable.hpp>
#include "se_std.h"

using namespace std;
/*服务器权重系数配置类*/
class se_server {
private:
    /*此服务器配置时的权重系数,用于恢复服务器*/
    const INT4 m_oldweight;
    INT4 m_weight, m_curweight;
public:
    se_server(const INT4 &weight) :
        m_weight(weight), m_oldweight(weight), m_curweight(0) {}
    se_server(const se_server &server) :
        m_weight(server.weight()), m_oldweight(server.oldweight()), m_curweight(server.curweight()) {}
    virtual ~se_server() {}
public:
    inline const INT4 &weight() const {
        return this->m_weight;
    }

    inline void weight(const INT4 &weight) {
        this->m_weight = weight;
    }

    inline const INT4 &curweight() const {
        return this->m_curweight;
    }

    inline void curweight(const INT4 &curweight) {
        this->m_curweight = curweight;
    }

    inline const INT4 &oldweight() const {
        return this->m_oldweight;
    }

    /*获取当前服务器是否健康*/
    inline bool health() const {
        return (0 == this->m_weight) ? false : true;
    }
};

/*实现平滑加权轮询(smooth weighted round-robin balancing)算法类*/
class se_balancer : public boost::noncopyable {
public:
    se_balancer() {}
    virtual ~se_balancer() {}
public:
    /*平滑加权轮询(smooth weighted round-robin balancing)算法*/
    inline INT4 get_next_server_index(vector<se_server> &ss) const {
        if (1 == ss.size())
            return 0;
        INT4 i(0), index(-1), total(0);
        for (vector<se_server>::iterator it(ss.begin()); it != ss.end(); ++it, ++i) {
            it->curweight((it->curweight() + it->weight()));
            total += it->weight();
            if (-1 == index || ss.at(index).curweight() < it->curweight()) {
                index = i;
            }
        }
        se_server &server = ss.at(index);
        server.curweight(server.curweight() - total);
        return index;
    }

    /*
    * 健康检查线程每过10分钟检查一次不健康的服务器
    * 如不健康的服务器可用时,恢复服务器为可用状态
    */
    inline void health(const INT4 &index, vector<se_server> &ss) const {
        se_server &server = ss.at(index);
        server.weight(server.oldweight());
        server.curweight(0);
    }

    /*
    * 不再使用不健康的数据库
    * 在服务中获取数据库链接后,检查连接状态为关闭时,该数据库将标记为不再使用
    * 然后再次通过get_next_server_index获取可使用的数据库
    * 如不健康的数据库恢复,数据库健康检查线程在过一段时间后恢复可用
    */
    inline void unhealthy(const INT4 &index, vector<se_server> &ss) const {
        se_server &server = ss.at(index);
        server.weight(0);
        server.curweight(0);
    }
};
#endif /* H_168E7C16_7638_4EE4_93F6_EE982858139D */

3 模拟测试

#include <cstdlib>
#include <iostream>
#include <vector>
#include "se_std.h"
#include "se_balancing.hpp"

using namespace std;

/*
 *
 */
int main(int argc, char** argv) {
    try {
        se_balancer balancer;
        /*保存服务数量和权重系数*/
        vector<se_server> ss;
        /*
         * 模拟设置4台服务器,使用系数分别为0、1、2、3
         * 其中权重系数为0的服务器永远不能使用
         */
        for (INT4 i(0); i < 4; ++i) {
            ss.push_back(se_server(i));
        }

        /*模拟100次请求分布到各个服务器的情况*/
        for (INT4 i(1); i <= 100; ++i)
            cout << "第" << i << "次请求:" << balancer.get_next_server_index(ss) << endl;
        return 0;
    } catch (se_exception &exp) {
        cerr << (*boost::get_error_info<se_error_message>(exp)) << endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值