缩放 .NET Core 极致性能的应用

 

介绍

.NET Core 和ASP.NET Core 由于其设计简单、轻量级、开源并且能够在 Windows 和 Linux 上运行而越来越受欢迎。 因此,许多现有的应用程序也正在迁移到 .NET Core 来自 .NET Framework. 几乎所有新的应用程序都在开发中 .NET Core.

其中很多 .NET Core 应用程序本质上是高流量的,服务于数百万用户和交易。 因此,这些应用程序会对您的业务产生巨大影响,因此非常重要。

 

谁需要可扩展性?

.NET Core 通常需要可扩展性的应用程序是服务器应用程序,它们必须以非常快的响应时间非常快速地处理大量事务。 其中许多应用程序都是面向客户的,这意味着它们正在处理客户请求。 如果他们不快速执行客户请求,那么在收入损失和失去满意客户方面,企业的成本就会很高。

跟随 .NET Core 应用程序需要可扩展性:

  1. 网络应用程序(ASP.NET Core): 这些通常是面向客户的应用程序,但也可能是面向大公司内部的应用程序。
  2. 网络服务(ASP.NET Core): 这些可以直接向客户提供 Web API,也可以是包含这些 Web 服务中的应用程序层逻辑的另一个高事务应用程序的一部分。
  3. 实时 Web 应用程序 (ASP.NET Core 信号R): 这些是必须使用 ASP 向用户提供频繁刷新的实时应用程序.NET Core的 SignalR 框架。 它们还必须快速执行,因为它们通常是面向客户的。
  4. 微服务 (.NET Core): 这是一种用于服务器端应用程序的新应用程序架构。 就像 Web 服务一样,这些微服务通常是面向客户的 Web 应用程序或面向客户的 Web 服务应用程序的一部分。 因此,它们在繁重的事务负载下也有高性能的要求。
  5. 其他服务器应用程序(.NET Core): 有大量其他服务器应用程序必须非常快速地处理大量事务。 这些可能是处理各种类型的后端工作流的批处理应用程序,也可能是接收大量数据以进行近乎实时处理的流处理应用程序。 名单还在继续。
 

问题:可扩展性瓶颈

有趣的是,上面提到的所有应用程序都具有非常可扩展的应用程序级架构。 它们中的每一个都允许您通过添加更多服务器、VM 或容器实例以及负载均衡器来随着事务负载的增长而线性扩展。

但是,尽管应用层的架构非常可扩展, .NET Core 今天的服务器应用程序面临着主要的可扩展性瓶颈。 这些瓶颈发生在不同的领域,例如:

  1. 应用程序数据库(关系数据库): 这是最大的瓶颈。 我在下面更详细地解释它。
  2. ASP.NET Core 会话存储: 如果会话存储在 SQL Server 中,那么您的 ASP.NET Core 应用将面临巨大的瓶颈。
  3. ASP.NET Core 重复页面处理: 如果重复执行相同的页面并且它们的输出或响应保持不变,那么这是资源浪费和性能瓶颈。
  4. ASP.NET Core SignalR Backplane 供应商: 如果使用 SignalR 的实时 Web 应用程序必须扩展,那么其 Backplane Provider 很容易成为瓶颈。
  5. Pub/Sub 消息传递(不在内存中): 如果你的 .NET Core 应用程序正在使用 Pub/Sub 消息传递,那么它很可能不是 In-Memory,因此是一个瓶颈。
ASP.NET Core 性能瓶颈
图 1:ASP.NET Core 应用程序面临可扩展性瓶颈
 

关系数据库瓶颈

所有高流量的最大瓶颈 .NET Core applications 是他们的应用程序数据库。 今天的大多数应用程序仍在使用关系数据库,如 SQL Server 或 Oracle。 随着您增加这些应用程序上的事务负载,这些数据库很快成为可伸缩性瓶颈。 无论您是在 VM 上使用 SQL Server 还是在 Azure SQL 数据库上使用,都是如此。

发生这种情况是因为关系数据库不能像 NoSQL database 而是留在一个物理位置; 甚至一些列级分区也不是真正的 NoSQL 风格分区。 因此,您无法通过添加更多数据库服务器来增加数据库层事务容量,就像使用 NoSQL database.

例如,虽然随着事务负载的增长,您的应用层可以轻松拥有 10、20、30 或更多的应用服务器,但您的数据库层根本无法以同样的方式增长。

由于这一切,您的关系数据库成为您存储在其中的任何数据(应用程序数据或其他数据)的性能瓶颈。

 

数据库服务器内存优化不够

SQL Server 引入了内存优化以增加每秒的事务数。 Oracle 还提供了他们自己的 In-Memory 表版本。

虽然内存优化带来了性能改进,但它们并没有解决线性可扩展性的核心问题。 In-Memory 表通常用于只读数据,为了扩展只读事务容量,您需要在更高端的机器上添加更多 SQL Server 实例。

In-Memory 表对数据的大小也有限制; 您不能将大表放在内存中,因为必须将整个表放在内存中。 并且它们到其他 SQL Server 实例的复制只能复制到其他 In-Memory 表而不是适当的数据库。

总之,SQL Server 和 Oracle 数据库中的这些内存优化无法完全解决您的 .NET Core 应用程序的可扩展性需求。

 

NoSQL Database 不是答案

其中一个原因 NoSQL databases 变得流行是因为它们提供了基于哈希和其他算法的适当数据分区。 这解决了 SQL Server 和 Oracle 等关系数据库面临的许多事务容量可扩展性问题。

但是,有原因 NoSQL databases 并不是这些数据库瓶颈的理想解决方案。

  1. 不是内存存储: NoSQL databases 将他们的数据存储在磁盘上,就像关系数据库一样。 这意味着无论你做什么,磁盘的缓慢性能最终都会成为性能瓶颈。
  2. 大部分时间无法使用: NoSQL databases 要求您放弃使用 SQL Server 和 Oracle 等关系数据库,并将它们替换为 NoSQL database. 由于技术和非技术原因,在大多数情况下这是不可能的。 本质上,您的业务依赖于您的关系数据库,不能轻易放弃它。 因此,您无法充分利用 NoSQL database.
 

解决方案:内存中分布式缓存(NCache)

上述所有问题的解决方案是使用 In-Memory Distributed Cache,如 NCache 在您的 .NET Core 应用部署。 NCache 是 .NET 的开源分布式缓存和 .NET Core 这是非常快速和线性可扩展的。 将其视为也是分布式的内存数据存储。 在内存中使其速度非常快,而分布式使其具有线性可扩展性。

NCache 是线性可扩展的,因为它构建了一个低成本缓存服务器的 TCP 集群(与您的 Web 应用程序服务器相同的配置,但具有更多内存)并将所有这些服务器的内存和 CPU 资源汇集到一个逻辑容量中。 NCache 然后允许您随着事务负载的增长在运行时将缓存服务器添加到此集群。 而且,由于 NCache 全部在内存中,速度超快,为您提供亚毫秒级的响应时间,这是您无法从关系数据库甚至是 NoSQL databases.

除了提供线性可扩展性之外,分布式缓存 NCache 智能地复制数据,因此您的性能不会受到影响,同时在任何缓存服务器出现故障的情况下实现数据可靠性。

NCache 部署在企业中 .NET Core
图2: NCache 部署在企业中 .NET Core

NCache 让你扩展你的 .NET Core 通过以下方式申请:

  • 应用程序数据缓存
  • ASP.NET Core 会话存储
  • ASP.NET Core 响应缓存中间件
  • ASP.NET Core SignalR Backplane
  • Pub/Sub 消息传递和 CQ 事件(内存中)
  • 连续查询事件(内存中)
 

应用程序数据缓存

面临的最重要瓶颈 .NET Core 应用程序是“应用程序数据库”。 关于美好的事情 NCache 是不是不像 NoSQL databases, NCache 不会要求您停止使用现有的关系数据库。 您可以继续使用 SQL Server、Azure SQL 数据库、Oracle 等作为您的数据库,并且仍然可以通过使用实现线性可伸缩性 NCache 在您的关系数据库之上。 这是因为 NCache 消除了所有关系数据库的可扩展性瓶颈,因为与您的数据库不同, NCache 实际上是线性可扩展的。

应用程序数据缓存使您能够消除数据库瓶颈。 NCache 允许您缓存应用程序数据并减少那些昂贵的数据库访问。 您可以预期将 80-90% 的数据库流量转移到 NCache. 这减少了数据库的压力,并允许它更快地执行并处理更大的事务负载而不会减慢速度。

应用程序数据缓存意味着您缓存从关系数据库获得的任何应用程序数据。 这通常采用域对象(也称为实体)的形式。 这是一个如何使用分布式缓存的示例 NCache 用于应用程序数据缓存。

Customer Load(string custId)
{
   ICache cache = CacheManager.GetCache("myCache");
   string key = "Customer:CustomerID:" + custId;
   Customer cust = cache.Get<Customer>(key);
   
   if (cust == null) {
   // Item not in cache so load from db
   LoadCustomerFromDb(cust);
   // Add item to cache for future reference
   cache.Add(key, cust);
   }
   return cust;
}

图 3:使用内存中分布式缓存进行应用数据缓存

 

ASP.NET Core 会话存储

另一个可能的瓶颈是如果你存储你的 ASP.NET Core SQL Server 或独立 MemoryCache 中的会话。 这两个选项在性能和可扩展性方面都有很大的限制。 SQL Server 存储不适合 ASP.NET Core 会话并很快成为瓶颈,就像应用程序数据一样。

NCache 是存储 ASP 的好地方.NET Core 会话,因为它比其他存储选项更快且更具可扩展性。 NCache 更快,因为它在内存中,并提供一个键值接口,其值是 ASP 的“对象”.NET Core 会话是。 而且,它是可扩展的,因为它是一个分布式缓存。

而且, NCache 还智能复制 ASP.NET Core 通过其丰富的缓存拓扑进行会话,因此即使缓存服务器出现故障,也不会丢失会话数据。 这种复制是必要的,因为 NCache 提供内存存储,而内存是违反存储的。

NCache 还可以加快 ASP 的序列化.NET Core 在进程外存储之前需要的会话。 NCache 通过使用比常规 .NET 快 10 倍的动态压缩序列化功能和 .NET Core 序列化。 您无需更改任何代码即可使用此功能。

您可以使用 NCache 作为您的 ASP.NET Core 会话存储有两种方式。

  1. 用于 ASP 的 IDistributedCache.NET Core 会议: NCache 实现了 IDistributedCache 接口,可以让你自动插件 NCache 作为您的 ASP.NET Core 会话存储提供程序。 但这比其他选项具有更少的功能。
  2. NCache ASP 提供者.NET Core 会议: NCache 还实现了自己的功能更丰富的 ASP.NET Core 您可以使用的会话存储提供程序。 它在额外锁定、超时等方面具有更多功能。

下面是如何配置 ASP 的示例.NET Core 要使用的应用程序 NCache 会话提供者:

public class Startup
{
   public void ConfigureServices(IServiceCollection services)
   {
      // Specify NCache as the session provider
      services.AddNCacheSession(Configuration.GetSection("NCacheSettings"));
	  ...
   }
   
   public void Configure(IApplicationBuilder app, ...)
   {   
      // select NCache session provider for ASP.NET Core
      app.UseNCacheSession();
      ...
   }
}

图 4:插件 NCache 作为ASP.NET Core 会议

 

ASP.NET Core 响应缓存中间件

ASP.NET Core 原本具有相当动态内容的应用程序面临这样的情况,即对于它们的某些页面,内容或响应不会在多个请求中发生变化。 但是这些页面仍然必须在每次请求到来时执行。 而且,这会给 Web 服务器资源以及该应用程序的所有层带来不必要的负担。 结果,这也增加了性能瓶颈并限制了应用程序的可扩展性。

public class Startup
{
   public void ConfigureServices(IServiceCollection services)
   {
      // Turn on ASP.NET Core Response Cache with IDistributedCache
      services.AddResponseCaching();
	  
      // Select NCache as IDistributedCache provider
      services.AddNCacheDistributedCache(Configuration.GetSection("NCacheSettings"));
      ...
   }
}

图 5:插件 NCache 作为ASP.NET Core 响应缓存中间件

为了解决页面响应不变的重复页面执行的开销,ASP.NET Core 提供了一种页面响应缓存机制,称为 ASP.NET 响应缓存中间件。 和, NCache 在 ASP 中实现了 IDistributedCache 接口.NET Core 因此,您可以无缝插入 NCache 作为您的 ASP.NET Core 响应缓存中间件。

因此,您可以使用 NCache 缓存 ASP.NET Core 页面响应一段时间,因此下次使用相同的参数调用相同的页面时,可以重新调整此缓存的响应,而不是再次执行整个页面。 下面是如何配置的代码示例 NCache 作为您的 ASP.NET Core 响应缓存中间件。

 

ASP.NET Core SignalR Backplane

如果你的 ASP.NET Core 应用程序是一个实时 Web 应用程序,那么它很可能使用 ASP.NET Core SignalR 用于提供这种实时行为。 实时 Web 应用程序提供从服务器到客户端的高频更新。 此类应用的示例包括游戏、拍卖、投票、社交网络等。

如果你的 ASP.NET Core 应用程序在负载平衡的多服务器环境中运行,那么它必须使用 ASP.NET Core SignalR Backplane 提供者,以便在多个 Web 服务器之间共享事件。 而且,这个背板必须是可扩展的。 否则,您的 ASP.NET Core SignalR 应用程序开始面临性能瓶颈。

public class Startup
{
   public void ConfigureServices(IServiceCollection services)
   {
   // Specify NCache as the ASP.NET Core SignalR Backplane
   services.AddSignalR().AddNCache(ncacheOptions =>
      { ncacheOptions.CacheName = "myPartitionedCache"; });
      ...
   }
   public void Configure(IApplicationBuilder app, ...)
   {
      // Use SignalR in ASP.NET Core
      app.UseSignalR(config => { config.MapHub<MessageHub>("/messages"); });
      ...
   }
}

图 6:插件 NCache 作为ASP.NET Core SignalR Backplane Provider

NCache 已实施 ASP.NET Core SignalR Backplane 供应商。 NCache的ASP.NET Core SignalR Backplane 提供商使用 Pub/Sub 消息传递功能 NCache 由于完全在内存中,所以速度非常快。 这允许您的 ASP.NET Core SignalR 应用程序可加速 SignalR 事件在所有 Web 服务器之间的传播,从而加速到客户端。

并且,这使您的实时 Web 应用程序在向客户端提供这些频繁更新时更具响应性。 而且,您可以不断增加客户端数量并添加更多 Web 服务器,而不必担心任何性能瓶颈。

 

Pub/Sub 消息传递(内存中)

如果你的 .NET Core 应用程序需要使用 Pub/Sub 消息传递或事件,那么它很可能使用不是完全在内存中的 Pub/Sub 消息传递平台,而是将所有消息存储在磁盘上。 因此,如果您的应用程序是真正的高事务,这很容易成为性能瓶颈。

NCache 还提供了超快的 Pub/Sub 消息传递,因为它完全是内存中的。 而且,它将所有消息复制到另一个 NCache 服务器以确保在任何一台服务器宕机的情况下不会丢失数据。

因此,如果您的 .NET Core 应用程序使用 NCache 作为其 Pub/Sub 消息传递平台,它将体验到超快的性能和线性可扩展性,因为 NCache 本身是线性可扩展的。

下面是如何使用 Pub/Sub 消息传递的示例,由 NCache 在您的 .NET Core 应用程序。

private void PublishMessage (string topicName)
{
    ITopic topic = _cache.MessagingService.GetTopic(topicName);
     Order order = Order.GenerateOrder<Order>();
     // Publish message containing "order" with expiry
     Message message = new Message(order, new TimeSpan(0, 0, 15));
     topic.Publish(message, DeliveryOption.All, true);
}

private ITopicSubscription SubscribeMessage (string topicName)
{
    ITopic topic = _cache.MessagingService.GetTopic(topicName);
    // Subscribes to the topic. Message delivered to MessageReceivedCallback
    return topic.CreateSubscription(MessageReceivedCallback);
}

static void MessageReceivedCallback(object sender, MessageEventArgs args) { ... }

图 7:使用 Pub/Sub 消息传递 .NET Core 应用

 

应用程序数据缓存

您最大的可扩展性瓶颈 .NET Core 应用程序必须从应用程序数据库中删除。 在这方面,您的应用程序可以通过应用程序数据缓存实现高性能和线性可扩展性。 这样做的原因是简单的。 最多 .NET Core 应用程序处理来自数据库的大量数据。

 

保持缓存新鲜

当谈到应用程序数据缓存时,人们最大的恐惧是缓存变得陈旧,这意味着它包含已由另一个用户或另一个应用程序在数据库中更改的旧版本数据。

  1. 参考与交易数据

    这种对缓存过时的恐惧是如此强烈,以至于大多数人只缓存只读或静态数据(参考数据)。 但是,这些只读数据仅占查找表和其他参考数据形式的总数据的 20%。 数据库中的大部分数据都是事务性的,包括客户、帐户、活动等。而且,如果您不缓存这些事务性数据,那么您就不会从缓存中充分受益。

    因此,如果您可以缓存所有类型的数据,而不必担心缓存变得陈旧,那么缓存的真正好处就来了。 NCache 提供了许多功能来解决这个问题。

  2. 将缓存与数据库同步

    保持缓存最新的最有效方法是始终使其与数据库保持同步。 NCache 允许您对各种数据库执行此操作,如下所示:

    1. 与 SQL Server 同步缓存: 使用 SqlDependency 和 DB 事件通知
    2. 与 Oracle 同步缓存: 使用 OracleDependency 和 DB 事件通知
    3. 与 Cosmos DB 同步缓存: 使用 Cosmos DB 更改馈送处理
    4. 与任何数据库同步缓存(基于轮询): 运用 NCache 提供基于轮询的数据库同步。

当您将缓存与 SQL Server 同步时,您会问 NCache 将自己注册为 SQL Server 的客户端,然后发出 SqlDependency 调用以及基于 SQL 查询的数据集。 然后,当 SQL Server 看到此数据集中的任何更改时,它会通知 NCache 关于它

private static void CreateSqlDependency (Product product)
{
 string connectionString = "Data Source=localhost;Database=northwind;...";
 // SQL stmt on which the SQL Dependency is created in SQL Server
 string sqlStmt = "SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice " +
 "FROM dbo.PRODUCTS WHERE ProductID = " + product.Id;
 CacheDependency sqlDependency = new SqlCacheDependency(connectionString, sqlStmt);
 CacheItem cacheItem = new CacheItem(product) { Dependency = sqlDependency };
 string key = "Product:ProductId:" + product.Id; ;
 cache.Add(key, cacheItem);
}

图 8:使用 SqlDependency 与 SQL Server 同步缓存

然后, NCache 从缓存中删除这个项目,所以下次应用程序需要它时,它必须从数据库中获取最新的副本。 如果您使用的是通读处理程序(见下文),那么 NCache 还可以为您自动重新加载数据库中的最新副本。 下面是一个示例,说明如何使用 SqlDependency 将缓存与 SQL Server 同步。

 

直读和直写缓存

Read-through Cache 是一种缓存,它能够通过调用您开发并提供给缓存的 Readthrough Handler 从数据库中读取数据。 类似地,直写缓存能够通过调用您开发并提供给缓存的直写处理程序将数据更改写入数据库。 Write-behind Cache 与 Write-through 相同,只是数据库更新是异步完成的。

Read-through、Write-through 和 Write-behind 为您提供了很多好处 .NET Core 应用包括:

  1. 简化应用程序代码: 将持久性代码从应用程序移出到缓存层。
  2. 从数据库自动重新加载项目: 在到期或数据库同步时使用通读。
  3. 更快的写入: 使用带有 write-behind 的异步数据库写入。

下面是一个示例,说明如何使用 Read-through with NCache.

// Read through handler for SQL Server
public class SqlReadThruProvider : Runtime.DatasourceProviders.IReadThruProvider
{
 public void Init(IDictionary parameters, string cacheId) {}
 public void Dispose() {}
 // Get object from the database/data-source based on the key
 public ProviderCacheItem LoadFromSource(string key) {}
 // Bulk-Get objects from the database/data-source based on the keys
 public IDictionary<string, ProviderCacheItem> LoadFromSource(ICollection<string> keys)
 {}
}

图 9:使用 Read-through Handler NCache

 

搜索缓存

一旦您对缓存所有数据感到满意,您就可以开始将大量数据放入分布式缓存中。 在这里,您可以开始面临如何快速轻松地找到您的数据的另一个特殊问题。 由于大多数分布式缓存都是键值存储,因此仅通过键来跟踪所有数据变得非常困难。

这是哪里 NCache 为您提供多种快速从缓存中查找数据的方法。 示例包括:

  1. 缓存中的组数据(组/子组、标签、命名标签): NCache 为您提供多种方式对数据进行逻辑分组,然后在一次调用中获取整个组。 这确实简化了您的数据管理。
  2. 使用查询搜索数据 (SQL / LINQ):除了基于组 API 调用查找数据外, NCache 还使您能够根据对象属性、组、标签和命名标签在缓存中搜索数据。
  3. 并行搜索:自 NCache 本质上是分布式的,当您的应用程序发出搜索查询或搜索 API 调用时,该查询将在所有缓存服务器上并行运行。 然后,来自所有服务器的结果将返回到客户端计算机(即应用程序服务器),在将最终结果返回到您的应用程序之前将它们合并。 这确实加快了您的缓存搜索速度。

下面是一个示例,说明如何使用基于 LINQ 的查询 NCache.

 // Search the cache based on object attributes by using LINQ
IQueryable>Product< products = new NCacheQuery<Product>(_cache);
var result = from product in products
where product.Id > 10
select product;
if (result != null)
   {
   foreach (Product p in result1)
      {
	     // Process each “product” fetched from the database
	     Console.WriteLine("ProductID : " + p.Id);
      }
   }

图 10:使用 LINQ 查询 NCache

 

NCache 极端可扩展性架构

交通拥挤 .NET Core 应用程序不能下降,尤其是在高峰时段。 对于这些类型的应用程序,良好的 InMemory 分布式缓存具有三个非常重要的架构目标 NCache 满足。

  1. 客户端缓存(InProc 速度)
  2. 具有快速复制的线性可扩展性
  3. 通过动态集群实现高可用性

让我在下面解释每一个。

 

客户端缓存(InProc 速度)

NCache 提供一个客户端缓存,它是一个非常靠近您的应用程序的本地缓存。 它可以是 InProc(意味着它驻留在您的应用程序进程中)或本地 OutProc。 无论哪种方式,它都可以非常快速地访问此应用服务器上的应用程序此时需要的缓存数据子集。 客户端缓存同时与缓存层保持同步,因此缓存层中其他用户或应用程序更改的任何数据都会立即传播到客户端缓存。 客户端允许您拥有 InProc 速度,同时仍然是非常可扩展的缓存层的一部分。

客户端缓存架构 NCache 对于 InProc 速度
图 11:客户端缓存架构 NCache 对于 InProc 速度
 

具有快速复制的线性可扩展性

最重要的架构目标之一 NCache 是通过其缓存拓扑实现具有数据可靠性的线性可扩展性。 这里有一些 NCache 缓存拓扑 这有助于实现这两个目标。

  1. 分区缓存: NCache 根据缓存服务器的数量对缓存进行分区,并为每个缓存服务器分配一个分区。 当您在运行时添加或删除缓存服务器时,它还会调整分区数。 分区是确保线性可扩展性的主要方式,因为当您添加更多服务器时,这种缓存拓扑会增加整体存储大小和 CPU 处理能力。
  2. 分区副本缓存: 除了分区, NCache 还为每个分区提供副本。 这些副本驻留在与分区本身不同的缓存服务器上,以确保如果缓存服务器与其分区一起出现故障,则副本立即变得可用。 这样,提供了数据可靠性。 通过在另一个缓存服务器上只复制每个分区一次, NCache 在不影响线性可扩展性的情况下实现数据可靠性。
分区副本缓存拓扑 NCache
图 12:分区副本缓存拓扑 NCache
 

100% 正常运行时间的高可用性

最重要的架构目标之一 NCache 就是实现高可用和缓存弹性。 它通过以下架构功能做到这一点:

  1. 自愈对等缓存集群: NCache 通过 TCP/IP 构建缓存服务器集群。 这个集群有一个 对等架构 这意味着没有主/从节点,也没有多数规则集群。 相反,每个节点都是平等的对等点。 这使 NCache 处理任何节点可能出现故障的情况,并且集群会自动调整并继续运行,并且您的应用程序不会中断。
  2. 动态配置: 这意味着您不必在配置文件中进行硬编码。 NCache 在运行时将配置信息传播到所有缓存客户端(即您的应用程序)。
  3. 连接故障转移支持: 如果缓存服务器出现故障,整个缓存集群和所有缓存客户端都可以继续工作而不会中断。 缓存客户端通过与集群中的其他缓存服务器交互来继续工作。

接下来做什么?

联系我们

联系电话
©版权所有 Alachisoft 2002 - 版权所有。 NCache 是 Diyatech Corp. 的注册商标。