IT

노드.js vs.순실적

itgroup 2023. 5. 28. 20:36
반응형

노드.js vs.순실적

Node.js가 빠르고 많은 양의 부하를 수용할 수 있다는 것을 많이 읽었습니다.특히 이것과 다른 프레임워크에 대한 실제 증거를 가진 사람이 있습니까?넷? 제가 읽은 기사들은 대부분 일화적이거나 비교가 되지 않습니다.그물.

빠른 것과 많은 부하를 처리하는 은 서로 다른 것입니다.초당 1개의 요청을 처리하는 속도가 정말 빠른 서버는 로드 상태에서 초당 500개의 요청을 전송하면 완전히 중단될 수 있습니다.

또한 정적(및 캐시) 페이지와 동적 페이지를 고려해야 합니다.정적 페이지가 걱정되는 경우 IIS가 커널 모드 캐싱을 사용하기 때문에 IIS가 노드를 이길 수 있습니다. 즉, 정적 페이지를 요청하는 요청은 커널 밖으로 나가지도 않습니다.

ASP.NET과 노드를 비교하는 방법을 찾고 계신 것 같습니다.이 전투에서는 모든 것이 컴파일/해석된 후 성능이 상당히 향상될 것입니다.아마도요.NET이 조금 더 빠르거나 노드가 조금 더 빠르지만, 아마 신경 쓰지 않을 정도로 충분히 가깝습니다..NET을 걸고 싶지만, 확실히는 모르겠습니다.

노드가 정말 매력적인 부분은 LOAD를 처리하기 위한 것입니다.이것이 바로 기술이 정말로 다른 점입니다. ASP.NET은 스레드 풀에서 각 요청에 대해 스레드를 전용하며, ASP.NET이 사용 가능한 스레드 요청을 모두 사용하면 대기열에 대기하기 시작합니다.@shankar의 예와 같은 "Hello World" 앱을 제공하는 경우 스레드가 차단되지 않고 스레드가 부족해지기 전에 많은 요청을 처리할 수 있기 때문에 크게 문제가 되지 않을 수 있습니다.ASP.NET 모델의 문제는 스레드를 차단하는 I/O 요청(DB로 호출, 서비스로 http 요청, 디스크에서 파일 읽기)을 시작할 때 발생합니다.이러한 차단 요청은 스레드 풀의 중요한 스레드가 아무 작업도 하지 않음을 의미합니다.차단이 많을수록 ASP.NET 앱의 로드가 줄어듭니다.

이 차단을 방지하기 위해 응답을 기다리는 동안 스레드를 유지할 필요가 없는 I/O 완료 포트를 사용합니다. ASP.NET은 이를 지원하지만 안타깝게도 .NET의 일반적인 프레임워크/라이브러리 중 상당수는 지원하지 않습니다.예를 들어 ADO.NET은 I/O 완료 포트를 지원하지만 Entity Framework는 이 포트를 사용하지 않습니다.따라서 순수하게 비동기식이고 많은 부하를 처리하는 ASP.NET 앱을 만들 수 있지만 대부분의 사람들은 동기식 앱을 만드는 것만큼 쉽지 않고 프레임워크에서 좋아하는 부분(예: 엔티티 링크)을 사용하지 못할 수도 있기 때문에 그렇게 하지 않습니다.

문제는 ASP.NET(및 .NET Framework)이 비동기 I/O에 대해 의견을 달리하도록 생성되었다는 점입니다. .NET은 사용자가 동기 코드를 작성하든 비동기 코드를 작성하든 상관하지 않으므로 이러한 결정은 개발자의 몫입니다.비동기식 작업으로 스레드화 및 프로그래밍을 하는 것이 "어렵다"고 생각되었기 때문에 .NET은 모든 사람(전문가 및 전문가 없음)을 만족시키기를 원했습니다..NET은 비동기 작업을 수행하는 데 3-4가지 패턴이 있기 때문에 더욱 어려워졌습니다. .NET 4.5는 .NET 프레임워크를 다시 개선하여 비동기 IO에 대한 의견을 제시하는 모델을 가지려고 하지만, 관심 있는 프레임워크가 실제로 이를 지원하기까지는 시간이 걸릴 수 있습니다.

반면 노드의 설계자들은 모든 I/O가 비동기여야 한다는 확고한 선택을 했습니다.이러한 결정으로 인해 노드 설계자는 노드의 각 인스턴스가 스레드 전환을 최소화하기 위해 단일 스레드가 될 것이며 스레드 하나가 대기열에 있던 코드를 실행할 것이라는 결정을 내릴 수 있었습니다.새 요청일 수도 있고, DB 요청의 콜백일 수도 있고, 사용자가 만든 http rest 요청의 콜백일 수도 있습니다.노드는 스레드 컨텍스트 스위치를 제거하여 CPU 효율성을 극대화하려고 합니다.노드는 모든 I/O가 비동기적이라는 확고한 선택을 했기 때문에 모든 프레임워크/추가 기능이 이 선택을 지원합니다.노드가 비동기식 앱을 강제로 작성하기 때문에 노드에서 100% 비동기식 앱을 작성하는 것이 더 쉽습니다.

다시 말하지만, 저는 어떤 식으로든 증명할 수 있는 어려운 숫자는 없지만, 일반적인 웹 앱의 LOAD 경쟁에서 노드가 이길 것이라고 생각합니다.고도로 최적화된(100% 비동기식) .NET 앱을 사용하면 동일한 node.js 앱을 실행할 수 있지만, 모든 .NET 및 모든 노드 앱의 평균을 사용하면 평균 노드에서 더 많은 로드를 처리할 수 있습니다.

나는 nodejs와 IIS 사이에서 기본적인 성능 테스트를 했습니다.IIS는 "hello, world!"를 배포할 때 nodejs보다 약 2.5배 더 빠릅니다.아래의 코드

내 하드웨어:Dell Latitude E6510, Core i5(듀얼 코어), 8GB RAM, Windows 7 Enterprise 64비트 OS

노드 서버

runs at http://localhost:9090/
/// <reference path="node-vsdoc.js" />
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("<p>hello, world!</p>");
response.end();
}).listen(9090);

default.htm

hosted by iis at http://localhost/test/
<p>hello, world!</p>

작업 병렬 라이브러리를 사용하는 나만의 벤치마크 프로그램:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace HttpBench
{
class Program
{
    private int TotalCount = 100000;
    private int ConcurrentThreads = 1000;
    private int failedCount;
    private int totalBytes;
    private int totalTime;
    private int completedCount;
    private static object lockObj = new object();

    /// <summary>
    /// main entry point
    /// </summary>
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run(args);
    }

    /// <summary>
    /// actual execution
    /// </summary>
    private void Run(string[] args)
    {
        // check command line
        if (args.Length == 0)
        {
            this.PrintUsage();
            return;
        }
        if (args[0] == "/?" || args[0] == "/h")
        {
            this.PrintUsage();
            return;
        }

        // use parallel library, download data
        ParallelOptions options = new ParallelOptions();
        options.MaxDegreeOfParallelism = this.ConcurrentThreads;
        int start = Environment.TickCount;
        Parallel.For(0, this.TotalCount, options, i =>
            {
                this.DownloadUrl(i, args[0]);
            }
        );
        int end = Environment.TickCount;

        // print results
        this.Print("Total requests sent: {0}", true, this.TotalCount);
        this.Print("Concurrent threads: {0}", true, this.ConcurrentThreads);
        this.Print("Total completed requests: {0}", true, this.completedCount);
        this.Print("Failed requests: {0}", true, this.failedCount);
        this.Print("Sum total of thread times (seconds): {0}", true, this.totalTime / 1000);
        this.Print("Total time taken by this program (seconds): {0}", true, (end - start) / 1000);
        this.Print("Total bytes: {0}", true, this.totalBytes);
    }

    /// <summary>
    /// download data from the given url
    /// </summary>
    private void DownloadUrl(int index, string url)
    {
        using (WebClient client = new WebClient())
        {
            try
            {
                int start = Environment.TickCount;
                byte[] data = client.DownloadData(url);
                int end = Environment.TickCount;
                lock (lockObj)
                {
                    this.totalTime = this.totalTime + (end - start);
                    if (data != null)
                    {
                        this.totalBytes = this.totalBytes + data.Length;
                    }
                }
            }
            catch
            {
                lock (lockObj) { this.failedCount++; }
            }
            lock (lockObj)
            {
                this.completedCount++;
                if (this.completedCount % 10000 == 0)
                {
                    this.Print("Completed {0} requests.", true, this.completedCount);
                }
            }
        }
    }

    /// <summary>
    /// print usage of this program
    /// </summary>
    private void PrintUsage()
    {
        this.Print("usage: httpbench [options] <url>");
    }

    /// <summary>
    /// print exception message to console
    /// </summary>
    private void PrintError(string msg, Exception ex = null, params object[] args)
    {
        StringBuilder sb = new System.Text.StringBuilder();
        sb.Append("Error: ");
        sb.AppendFormat(msg, args);
        if (ex != null)
        {
            sb.Append("Exception: ");
            sb.Append(ex.Message);
        }
        this.Print(sb.ToString());
    }

    /// <summary>
    /// print to console
    /// </summary>
    private void Print(string msg, bool isLine = true, params object[] args)
    {
        if (isLine)
        {
            Console.WriteLine(msg, args);
        }
        else
        {
            Console.Write(msg, args);
        }
    }

}
}

및 결과:

IIS: httpbench.exe http://localhost/test

Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 97
Total time taken by this program (seconds): 16
Total bytes: 2000000

nodejs: httpbench.exe http://localhost:9090/

Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 234
Total time taken by this program (seconds): 27
Total bytes: 2000000

결론: IIS는 nodejs보다 약 2.5배 빠릅니다(Windows의 경우).이것은 매우 초보적인 테스트이며 결코 결정적인 테스트는 아닙니다.하지만 저는 이것이 좋은 출발점이라고 믿습니다.Nodejs는 다른 웹 서버, 다른 플랫폼에서 더 빠를 수 있지만 Windows IIS에서는 더 빠릅니다.ASP.NET MVC를 nodejs로 변환하려는 개발자는 계속하기 전에 일시 중지하고 다시 생각해야 합니다.

업데이트됨(2012년 5월 17일) Tomcat(윈도우에서)은 정적 html을 배포하는 데 IIS보다 약 3배 빠른 IIS 핸드다운을 능가하는 것으로 보입니다.

톰캣

index.html at http://localhost:8080/test/
<p>hello, world!</p>

tomcat 결과

httpbench.exe http://localhost:8080/test/
Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 31
Total time taken by this program (seconds): 5
Total bytes: 2000000

업데이트된 결론: 벤치마크 프로그램을 여러 번 실행했습니다.Tomcat은 WINDOWS에서 정적 HTML을 디스커버리하는 데 가장 빠른 서버로 보입니다.

업데이트됨(2012년 5월 18일) 이전에는 총 100,000건의 요청과 10,000건의 동시 요청이 있었습니다.총 1,000,000개의 요청과 100,000개의 동시 요청으로 늘렸습니다.IIS는 Nodejs가 최악의 페어를 하는 가운데 비명을 지르는 승자로 나옵니다.아래에 결과를 표로 정리했습니다.

Windows에서 정적 HTML을 제공하는 NodeJS vs IIS vs Tomcat.

NIO 서버(Node.js 등)는 BIO 서버보다 빠른 경향이 있습니다.(IIS 등).제 주장을 뒷받침하기 위해 TechEmpower는 웹 프레임워크 벤치마크에 특화된 회사입니다.그들은 매우 개방적이고 모든 프레임 워크를 테스트하는 표준 방법을 가지고 있습니다.

9라운드 테스트는 현재 최신(2014년 5월)입니다.많은 IIS 버전이 테스트되었지만, aspnet-striped가 가장 빠른 IIS 버전인 것 같습니다.

다음은 초당 응답결과입니다(높을수록 좋습니다).

  • JSON 시리즈화
    • nodejs:228,887
    • aspnet-vlan:105,272
  • 단일 쿼리
    • nodejs-proxy:88,597
    • aspnet-snot-raw:47,066
  • 다중 쿼리
    • nodejs-proxy:8,878
    • aspnet-snot-raw:3,915
  • 일반 텍스트
    • nodejs:289,578
    • aspnet-vlan:109,136

모든 경우 Node.js는 IIS보다 2배 이상 빠른 경향이 있습니다.

저는 Marcus Granstrom의 의견에 동의합니다. 시나리오는 여기서 매우 중요합니다.

솔직히 말해서 당신은 영향력이 큰 건축적 결정을 내리는 것처럼 들립니다.제 조언은 우려되는 분야를 분리하여 고려 중인 스택 간에 "브레이크 오프"를 수행하는 것입니다.

결국 결정에 대한 책임은 당신에게 있으며 "스택 오버플로의 어떤 남자가 괜찮을 것이라고 말한 기사를 보여주었다"는 변명은 아니라고 생각합니다. 상사와 잘릴 것입니다.

제가 본 주요 차이점은 node.js가 동적 프로그래밍 언어(유형 확인)이므로 유형은 런타임에 파생되어야 한다는 것입니다.C# .NET과 같은 강력한 유형의 언어는 이론적으로 Node .js(및 PHP 등)와의 싸움에서 훨씬 더 많은 잠재력을 가지고 있습니다. 특히 계산 비용이 많이 드는 곳입니다.그런데 .NET은 node.js보다 C/C++과의 네이티브 상호 운용성이 더 좋아야 합니다.

언급URL : https://stackoverflow.com/questions/9290160/node-js-vs-net-performance

반응형