.NET Core 앱을 극한의 성능으로 확장하기

 

개요

.NET Core와 ASP.NET Core는 간결한 설계, 경량성, 오픈 소스, 그리고 Windows와 Linux 모두에서 실행 가능하다는 장점 덕분에 인기를 얻고 있습니다. 그 결과, 많은 기존 애플리케이션들이 .NET Framework에서 .NET Core로 전환되고 있으며, 거의 모든 새로운 애플리케이션들이 .NET Core로 개발되고 있습니다.

이러한 .NET Core 애플리케이션 중 상당수는 수백만 명의 사용자와 트랜잭션을 처리하는 고트래픽 애플리케이션입니다. 따라서 이러한 애플리케이션은 비즈니스에 큰 영향을 미치므로 매우 중요합니다.

 

누가 확장성을 필요로 합니까?

일반적으로 확장성이 필요한 .NET Core 애플리케이션은 매우 빠른 응답 속도로 많은 트랜잭션을 신속하게 처리해야 하는 서버 애플리케이션입니다. 이러한 애플리케이션 중 상당수는 고객 대면 애플리케이션으로, 고객 요청을 처리합니다. 고객 요청을 신속하게 처리하지 못하면 매출 손실과 고객 이탈로 인해 기업에 막대한 손해가 발생할 수 있습니다.

다음과 같은 .NET Core 애플리케이션에는 확장성이 필요합니다.

  1. 웹 애플리케이션(ASP.NET Core): 이들은 일반적으로 고객 대면 애플리케이션이지만 대기업을 위한 내부 대면 애플리케이션일 수도 있습니다.
  2. 웹 서비스(ASP.NET Core): 이들은 웹 API를 고객에게 직접 제공하거나 이러한 웹 서비스의 애플리케이션 계층 논리를 포함하는 다른 높은 트랜잭션 애플리케이션의 일부일 수 있습니다.
  3. 실시간 웹 애플리케이션(ASP.NET Core SignalR): 이 애플리케이션들은 ASP.NET Core의 SignalR 프레임워크를 사용하여 사용자에게 빈번한 화면 새로 고침을 제공해야 하는 실시간 애플리케이션입니다. 또한, 대부분 고객 대면 애플리케이션이므로 빠른 성능도 필수적입니다.
  4. 마이크로서비스(.NET Core): 이것은 서버측 애플리케이션을 위한 새로운 애플리케이션 아키텍처입니다. 그리고 웹 서비스와 마찬가지로 이러한 마이크로 서비스는 일반적으로 고객 대면 웹 애플리케이션 또는 고객 대면 웹 서비스 애플리케이션의 일부입니다. 결과적으로 트랜잭션 로드가 많은 경우에도 고성능 요구 사항이 있습니다.
  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 백플레인 공급자: SignalR을 사용하는 라이브 웹 앱이 확장되어야 하는 경우 백플레인 제공자가 쉽게 병목 현상이 될 수 있습니다.
  5. Pub/Sub 메시징(메모리 내 아님): .NET Core 애플리케이션에서 Pub/Sub 메시징을 사용하는 경우, 해당 메시징이 메모리에 저장되지 않으므로 병목 현상이 발생할 가능성이 높습니다.
ASP.NET 코어 성능 병목 현상
그림 1: ASP.NET Core 앱에서 발생하는 확장성 병목 현상
 

관계형 데이터베이스 병목 현상

트래픽이 많은 .NET Core 애플리케이션의 가장 큰 병목 현상은 애플리케이션 데이터베이스입니다. 오늘날 대부분의 애플리케이션은 여전히 ​​SQL Server나 Oracle과 같은 관계형 데이터베이스를 사용하고 있습니다. 이러한 데이터베이스는 애플리케이션의 트랜잭션 부하가 증가함에 따라 확장성 병목 현상을 빠르게 일으킵니다. 이는 가상 머신에서 SQL Server를 사용하든 Azure SQL Database를 사용하든 마찬가지입니다.

관계형 데이터베이스는 NoSQL 데이터베이스처럼 논리적으로 파티셔닝할 수 없고 물리적인 한 위치에만 존재하기 때문에 이러한 현상이 발생합니다. 심지어 일부 컬럼 수준 파티셔닝조차도 진정한 NoSQL 스타일의 파티셔닝과는 거리가 멉니다. 따라서 NoSQL 데이터베이스처럼 데이터베이스 서버를 추가하여 데이터베이스 계층의 트랜잭션 용량을 확장할 수 없습니다.

예를 들어 애플리케이션 계층은 트랜잭션 부하가 증가함에 따라 10, 20, 30개 이상의 애플리케이션 서버를 쉽게 가질 수 있지만 데이터베이스 계층은 같은 방식으로 전혀 성장할 수 없습니다.

이 모든 것 때문에 관계형 데이터베이스에 저장하는 모든 데이터(응용 프로그램 데이터 또는 기타 데이터)에 대한 성능 병목 현상이 발생합니다.

 

데이터베이스 서버 메모리 내 최적화가 충분하지 않음

SQL Server는 초당 트랜잭션 수를 늘리기 위해 메모리 내 최적화를 도입했습니다. Oracle은 자체 버전의 In-Memory 테이블도 제공했습니다.

In-Memory 최적화는 성능 향상을 가져오지만 선형 확장성의 핵심 문제는 해결하지 못합니다. In-Memory 테이블은 일반적으로 읽기 전용 데이터에 사용되며 읽기 전용 트랜잭션 용량을 확장하려면 고급 머신에 SQL Server 인스턴스를 더 추가해야 합니다.

In-Memory 테이블에는 데이터 크기에도 제한이 있습니다. 전체 테이블을 메모리에 넣어야 하므로 큰 테이블을 메모리에 넣을 수 없습니다. 그리고 다른 SQL Server 인스턴스에 대한 복제는 적절한 데이터베이스가 아닌 다른 In-Memory 테이블에 대해서만 수행할 수 있습니다.

요약하자면, SQL Server 및 Oracle 데이터베이스의 이러한 인메모리 최적화는 .NET Core 애플리케이션의 확장성 요구 사항을 완전히 충족할 수 없습니다.

 

NoSQL 데이터베이스는 해답이 아닙니다.

NoSQL 데이터베이스가 인기를 얻게 된 이유 중 하나는 해시 기반 알고리즘 등을 통해 데이터를 적절하게 분할할 수 있기 때문입니다. 이는 SQL Server나 Oracle과 같은 관계형 데이터베이스가 직면하는 트랜잭션 처리 용량 확장성 문제를 상당 부분 해결해 줍니다.

하지만 NoSQL 데이터베이스가 이러한 데이터베이스 병목 현상에 대한 이상적인 해결책이 아닌 데에는 이유가 있습니다.

  1. 메모리 내 저장소가 아님: NoSQL 데이터베이스는 관계형 데이터베이스처럼 데이터를 디스크에 저장합니다. 즉, 어떤 방법을 사용하더라도 디스크의 느린 성능이 결국 성능 병목 현상이 될 수밖에 없습니다.
  2. 대부분의 시간에 사용할 수 없음: NoSQL 데이터베이스를 사용하려면 SQL Server나 Oracle 같은 관계형 데이터베이스를 포기하고 NoSQL 데이터베이스로 대체해야 합니다. 하지만 기술적, 비기술적 이유로 대부분의 경우 이는 불가능합니다. 기본적으로 비즈니스 운영이 관계형 데이터베이스에 의존하고 있기 때문에 이를 쉽게 포기할 수 없습니다. 결과적으로 NoSQL 데이터베이스의 모든 장점을 활용할 수 없게 됩니다.
 

솔루션: 메모리 내 분산 캐시(NCache)

위에서 언급한 모든 문제에 대한 해결책은 다음과 같은 In-Memory Distributed Cache를 사용하는 것입니다. NCache .NET Core 애플리케이션 배포 시. NCache 는 .NET 및 .NET Core용 오픈 소스 분산 캐시로, 매우 빠르고 선형적으로 확장 가능합니다. 마치 메모리에 저장되는 데이터 저장소이면서 동시에 분산형 저장소라고 생각하시면 됩니다. 메모리에 저장되므로 속도가 매우 빠르고, 분산형이므로 선형적으로 확장 가능합니다.

NCache 저비용 캐시 서버의 TCP 클러스터(웹 앱 서버와 동일한 구성이지만 메모리가 더 많음)를 구축하고 이러한 모든 서버의 메모리 및 CPU 리소스를 하나의 논리적 용량으로 풀링하기 때문에 선형적으로 확장 가능합니다. NCache 그런 다음 트랜잭션 로드가 증가함에 따라 런타임 시 이 클러스터에 캐시 서버를 추가할 수 있습니다. 이후 NCache 모든 데이터가 메모리에 저장되므로 매우 빠르며, 관계형 데이터베이스나 NoSQL 데이터베이스에서는 기대할 수 없는 1밀리초 미만의 응답 시간을 제공합니다.

선형 확장성을 제공하는 것 외에도 다음과 같은 분산 캐시가 있습니다. NCache 데이터를 지능적으로 복제하므로 캐시 서버가 다운되는 경우에도 데이터 안정성을 유지하면서 성능이 저하되지 않습니다.

NCache .NET Core용 엔터프라이즈 환경에 배포
그림 2 : NCache .NET Core용 엔터프라이즈 환경에 배포

NCache 다음과 같은 방법을 통해 .NET Core 애플리케이션을 확장할 수 있습니다.

  • 애플리케이션 데이터 캐싱
  • ASP.NET 코어 세션 저장소
  • ASP.NET 코어 응답 캐시 미들웨어
  • ASP.NET 코어 SignalR 백플레인
  • Pub/Sub 메시징 및 CQ 이벤트(메모리 내)
  • 연속 쿼리 이벤트(메모리 내)
 

애플리케이션 데이터 캐싱

.NET Core 애플리케이션이 직면하는 가장 중요한 병목 현상은 "애플리케이션 데이터베이스"입니다. 하지만 좋은 점은... NCache NoSQL 데이터베이스와는 달리, NCache 기존 관계형 데이터베이스 사용을 중지하도록 요청하지 않습니다. SQL Server, Azure SQL Database, 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 코어 세션 저장소

또 다른 잠재적인 병목 현상은 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 및 .NET Core 직렬화보다 10배 빠른 동적 압축 직렬화(Dynamic Compact Serialization) 기능을 사용하여 구현됩니다. 코드 변경 없이 이 기능을 사용할 수 있습니다.

당신이 사용할 수 NCache ASP.NET Core 세션 저장소로 사용하는 방법은 두 가지입니다.

  1. ASP.NET Core 세션용 IDistributedCache: 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 코어 응답 캐시 미들웨어

ASP.NET Core 애플리케이션은 일반적으로 매우 동적인 콘텐츠를 처리하지만, 일부 페이지의 콘텐츠나 응답이 여러 요청에 걸쳐 변경되지 않는 상황에 직면할 수 있습니다. 하지만 이러한 페이지는 요청이 들어올 때마다 실행되어야 합니다. 이는 웹 서버 리소스와 애플리케이션의 모든 계층에 불필요한 부담을 가중시키고, 결과적으로 성능 병목 현상을 유발하며 애플리케이션의 확장성을 제한합니다.

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.NET Core에서 IDistributedCache 인터페이스를 구현했기 때문에 원활하게 플러그인할 수 있습니다. NCache ASP.NET Core 응답 캐시 미들웨어로 사용하세요.

그래서 당신은 사용할 수 있습니다 NCache ASP.NET Core 페이지 응답을 일정 기간 동안 캐시하여 다음에 동일한 페이지를 동일한 매개변수로 호출할 때 전체 페이지를 다시 실행하는 대신 캐시된 응답을 반환할 수 있습니다. 다음은 캐시를 구성하는 방법에 대한 코드 예제입니다. NCache ASP.NET Core 응답 캐시 미들웨어로 사용하세요.

 

ASP.NET 코어 SignalR 백플레인

ASP.NET Core 애플리케이션이 실시간 웹 애플리케이션이라면, 실시간 동작을 제공하기 위해 ASP.NET Core SignalR을 사용하고 있을 가능성이 높습니다. 실시간 웹 애플리케이션은 서버에서 클라이언트로 빈번하게 업데이트를 제공합니다. 이러한 애플리케이션의 예로는 게임, 경매, 투표, 소셜 네트워크 등이 있습니다.

ASP.NET Core 애플리케이션이 로드 밸런싱된 멀티 서버 환경에서 실행되는 경우, 여러 웹 서버에서 이벤트를 공유하기 위해 ASP.NET Core SignalR 백플레인 공급자를 사용해야 합니다. 그리고 이 백플레인은 확장 가능해야 합니다. 그렇지 않으면 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 백플레인 공급자로 사용

NCache ASP.NET Core SignalR 백플레인 공급자를 구현했습니다. NCacheASP.NET Core SignalR 백플레인 공급자는 Pub/Sub 메시징 기능을 사용합니다. NCache 이 기능은 완전히 메모리 내에서 작동하기 때문에 매우 빠릅니다. 이를 통해 ASP.NET Core SignalR 애플리케이션은 모든 웹 서버와 클라이언트 간에 SignalR 이벤트 전파 속도를 향상시킬 수 있습니다.

또한 이렇게 하면 클라이언트에 대한 빈번한 업데이트를 제공할 때 실시간 웹 애플리케이션의 응답성이 향상됩니다. 또한 성능 병목 현상에 대한 두려움 없이 클라이언트 수를 계속 늘리고 더 많은 웹 서버를 추가할 수도 있습니다.

 

Pub/Sub 메시징(메모리 내)

.NET Core 애플리케이션에서 Pub/Sub 메시징 또는 이벤트를 사용해야 하는 경우, 대부분의 경우 완전한 인메모리 방식이 아닌 디스크에 모든 메시지를 저장하는 Pub/Sub 메시징 플랫폼을 사용하고 있을 가능성이 높습니다. 따라서 애플리케이션의 트랜잭션 처리량이 매우 높을 경우 성능 병목 현상이 발생하기 쉽습니다.

NCache 또한 완전히 In-Memory이기 때문에 매우 빠른 Pub/Sub Messaging을 제공합니다. 그리고 모든 메시지를 다른 NCache 하나의 서버가 다운되는 경우 데이터 손실이 없는지 확인하는 서버입니다.

따라서 .NET Core 애플리케이션이 사용하는 경우 NCache Pub/Sub Messaging 플랫폼으로서 초고속 성능과 선형 확장성을 경험할 것입니다. NCache 자체적으로 선형 확장 가능합니다.

다음은 에서 제공하는 Pub/Sub Messaging을 사용하는 방법의 예입니다. 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: .NET Core 앱에서 Pub/Sub 메시징 사용하기

 

애플리케이션 데이터 캐싱

.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의 클라이언트로 등록한 다음 SQL 쿼리 기반 데이터 세트와 함께 SqlDependency 호출을 실행합니다. 그런 다음 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 캐시에서 이 항목을 제거하므로 다음에 응용 프로그램에서 필요할 때 데이터베이스에서 최신 복사본을 가져와야 합니다. Read-through 처리기를 사용하는 경우(아래 참조) NCache 데이터베이스에서 최신 복사본을 자동으로 다시 로드할 수도 있습니다. 다음은 SqlDependency를 사용하여 캐시를 SQL Server와 동기화하는 방법의 예입니다.

 

Read-through 및 Write-through 캐시

Read-through Cache는 개발자가 개발하여 캐시에 제공한 Readthrough Handler를 호출하여 데이터베이스에서 데이터를 읽을 수 있는 캐시입니다. 마찬가지로 Write-through 캐시는 개발자가 개발하여 캐시에 제공한 Write-through 핸들러를 호출하여 데이터 변경 사항을 데이터베이스에 기록할 수 있습니다. Write-behind 캐시는 데이터베이스 업데이트가 비동기식으로 수행된다는 점을 제외하면 Write-through와 동일합니다.

읽기-통과, 쓰기-통과 및 쓰기 지연은 .NET Core 애플리케이션에 다음과 같은 많은 이점을 제공합니다.

  1. 앱 코드 단순화: 지속성 코드를 애플리케이션에서 캐싱 계층으로 이동합니다.
  2. DB에서 항목 자동 다시 로드: 만료 또는 DB 동기화 시간에 Read-through를 사용합니다.
  3. 더 빠른 쓰기: write-behind와 함께 비동기 데이터베이스 쓰기를 사용합니다.

다음은 Read-through를 사용하는 방법의 예입니다. 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 핸들러 사용 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 애플리케이션은 특히 피크 시간대에 다운되는 것을 용납할 수 없습니다. 이러한 유형의 애플리케이션에는 우수한 인메모리 분산 캐시가 갖춰야 할 세 가지 중요한 아키텍처 목표가 있습니다. 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. 자가 치유 PXNUMXP 캐시 클러스터: NCache TCP/IP를 통해 캐시 서버 클러스터를 구축합니다. 이 클러스터에는 피어 투 피어 아키텍처 즉, 마스터/슬레이브 노드가 없고 다수결 클러스터링이 없습니다. 대신 각 노드는 동일한 피어입니다. 이를 통해 NCache 노드가 다운될 수 있고 클러스터가 자동으로 조정되고 계속 실행되고 애플리케이션에 중단이 없는 상황을 처리하기 위해.
  2. 동적 구성: 즉, 구성 파일에 무언가를 하드 코딩할 필요가 없습니다. NCache 런타임 시 구성 정보를 모든 캐시 클라이언트(애플리케이션을 의미)에 전파합니다.
  3. 연결 장애 조치 지원: 캐시 서버가 다운되면 전체 캐시 클러스터와 모든 캐시 클라이언트가 중단 없이 계속 작동할 수 있습니다. 캐시 클라이언트는 클러스터의 다른 캐시 서버와 상호 작용하여 계속 작동합니다.

다음에 무엇을할지?

문의하기

전화

+1 214-619-2601 (미국)

© 저작권 Alachisoft 2002 - . 판권 소유. NCache 는 Diyatech Corp.의 등록상표입니다.