创建高可用性AppFabric缓存集群

HOC*_*OCA 5 appfabric appfabric-cache

除了Secondaries=1在集群配置中设置启用HighAvailability 之外还有什么内容,特别是在缓存客户端配置上吗?

我们的配置:

使用about配置,我们可以看到在三台主机上创建的主区域和辅助区域,但是当其中一台主机停止时,会发生以下异常:

  • ErrorCode<ERRCA0018>:SubStatus<ES0001>:The request timed out.
  • An existing connection was forcibly closed by the remote host
  • No connection could be made because the target machine actively refused it 192.22.0.34:22233
  • An existing connection was forcibly closed by the remote host

高可用性是否能够在不中断服务的情况下处理主机停机?我们正在使用一个命名区域 - 这会破坏高可用性吗?我在某处读到命名区域只能存在于一个主机上(我确实验证了另一个主机上存在辅助区域).我觉得我们缺少一些缓存客户端配置可以实现高可用性,任何有关此事的见解都将非常感激.

dia*_*aho 1

在向 Microsoft 提出请求后,我们将范围缩小到拥有静态DataCacheFactory对象。

public class AppFabricCacheProvider : ICacheProvider
{
    private static readonly object Locker = new object();
    private static AppFabricCacheProvider _instance;
    private static DataCache _cache;

    private AppFabricCacheProvider()
    {
    }

    public static AppFabricCacheProvider GetInstance()
    {
        lock (Locker)
        {
            if (_instance == null)
            {
                _instance = new AppFabricCacheProvider();
                var factory = new DataCacheFactory();
                _cache = factory.GetCache("AdMatter");
            }
        }
        return _instance;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

从 AppFabric 中查看tracelog,客户端仍在尝试连接到所有主机,而不处理主机关闭的情况。在客户端上重置 IIS 会强制DataCacheFactory创建一个新的 IIS(在我们的 IIS 中App_Start)并停止异常。

MS 工程师一致认为这种方法是最佳实践方式(我们还找到了几篇关于此的文章:请参阅链接链接

他们正在继续为我们研究解决方案。同时,我们提出了以下临时解决方法,DataCacheFactory如果遇到上述异常之一,我们将强制创建一个新对象。

public class AppFabricCacheProvider : ICacheProvider
{
    private const int RefreshWindowMinutes = -5;

    private static readonly object Locker = new object();
    private static AppFabricCacheProvider _instance;
    private static DataCache _cache;
    private static DateTime _lastRefreshDate;

    private AppFabricCacheProvider()
    {
    }

    public static AppFabricCacheProvider GetInstance()
    {
        lock (Locker)
        {
            if (_instance == null)
            {
                _instance = new AppFabricCacheProvider();
                var factory = new DataCacheFactory();
                _cache = factory.GetCache("AdMatter");
                _lastRefreshDate = DateTime.UtcNow;
            }
        }
        return _instance;
    }

    private static void ForceRefresh()
    {
        lock (Locker)
        {
            if (_instance != null && DateTime.UtcNow.AddMinutes(RefreshWindowMinutes) > _lastRefreshDate)
            {
                var factory = new DataCacheFactory();
                _cache = factory.GetCache("AdMatter");
                _lastRefreshDate = DateTime.UtcNow;
            }
        }
    }

    ...

    public T Put<T>(string key, T value)
    {
        try
        {
            _cache.Put(key, value);
        }
        catch (SocketException)
        {
            ForceRefresh();
            _cache.Put(key, value);
        }
        return value;
    }
Run Code Online (Sandbox Code Playgroud)

当我们了解更多信息时将更新此线程。