解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
2.71 KiB
X
namespace NewLife.Remoting;

/// <summary>故障转移负载均衡器</summary>
/// <remarks>
/// 故障转移策略:
/// <list type="bullet">
/// <item><description>优先使用第一个(主)节点</description></item>
/// <item><description>主节点失败时自动切换到下一个备用节点</description></item>
/// <item><description>不可用节点被屏蔽一段时间(ShieldingTime)</description></item>
/// <item><description>屏蔽时间过后自动尝试切回主节点</description></item>
/// </list>
/// 适用场景:需要高可用保障的业务场景,确保业务连续性
/// </remarks>
public class FailoverLoadBalancer : LoadBalancerBase
{
    #region 属性
    /// <summary>负载均衡模式</summary>
    public override LoadBalanceMode Mode => LoadBalanceMode.Failover;

    /// <summary>当前服务索引</summary>
    private volatile Int32 _currentIndex;
    #endregion

    #region 方法
    /// <summary>获取一个服务用于处理请求</summary>
    /// <param name="services">服务列表</param>
    /// <returns>选中的服务节点</returns>
    public override ServiceEndpoint GetService(IList<ServiceEndpoint> services)
    {
        if (services == null || services.Count == 0)
            throw new InvalidOperationException("No available service nodes!");

        EnsureAvailable(services);

        // 优先尝试切回主节点
        var idx = _currentIndex;
        if (idx > 0 && services[0].IsAvailable())
        {
            idx = _currentIndex = 0;
            Log?.Debug("主节点[{0}]恢复可用,切回主节点", services[0].Name);
        }

        // 获取当前索引对应的服务
        var svc = services[idx % services.Count];
        svc.Times++;

        return svc;
    }

    /// <summary>归还服务,报告请求结果</summary>
    /// <param name="services">服务列表</param>
    /// <param name="service">归还的服务</param>
    /// <param name="error">异常信息,null表示成功</param>
    public override void PutService(IList<ServiceEndpoint> services, ServiceEndpoint service, Exception? error)
    {
        base.PutService(services, service, error);

        var ex = error;
        while (ex is AggregateException age) ex = age.InnerException;

        // 网络异常时,自动切换到下一个节点
        if (ex is HttpRequestException or TaskCanceledException)
        {
            var nextIndex = _currentIndex + 1;
            if (nextIndex < services.Count)
            {
                _currentIndex = nextIndex;
                Log?.Debug("服务节点[{0}]网络异常,切换到节点[{1}],使用地址:{2}", service.Name, services[nextIndex].Name, services[nextIndex].Address);
            }
        }
    }
    #endregion
}