Node.js アプリケーションの人気が高まるにつれて、スケーラビリティが重要な要素になります。パフォーマンスを低下させることなく、増加するリクエストを処理できる機能は、堅牢な実稼働対応アプリケーションにとって不可欠です。この記事では、垂直スケーリングから水平スケーリング、負荷分散、クラスタリングなどのより高度な方法まで、Node.js アプリケーションをスケーリングするためのさまざまな手法を検討します。
スケーラビリティとは、最適なパフォーマンスを維持しながらトラフィックの増加と需要の増大に対処するアプリケーションの能力です。スケーリングには主に 2 つのタイプがあります:
垂直スケーリングは簡単ですが、サーバーがどれほど強力であっても常に制限があるため、制限があります。水平スケーリングはより柔軟であり、大規模なアプリケーションに適しており、複数のサーバーに負荷を分散できます。
垂直スケーリングには、Node.js アプリケーションを実行するマシンの計算リソースの増加が含まれます。この方法は実装が簡単ですが、単一サーバーはある程度までしか拡張できないため、限界があります。
垂直スケーリングの手順:
ただし、垂直方向のスケーリングが限界に達したら、水平方向のスケーリングを検討する必要があります。
水平スケーリングには、複数のサーバー間でアプリケーションを実行し、それらのサーバー間で受信トラフィックを分散することが含まれます。この方法により、パフォーマンスと耐障害性の両方が向上します。 Node.js アプリケーションは、クラスタリング、負荷分散、クラウド サービスの使用など、いくつかの戦略を使用して水平方向に拡張できます。
デフォルトでは、Node.js プロセスは単一のスレッドで実行されます。ただし、最新のサーバーのほとんどには複数の CPU コアが搭載されています。マルチコア プロセッサを最大限に活用するには、それぞれが別のコアで実行される Node.js プロセスのクラスターを作成できます。 Node のクラスター モジュールを使用すると、これが簡単になります。
例: Node.js でクラスターを作成する
const cluster = require('cluster'); const http = require('http'); const os = require('os'); // Check if the current process is the master process if (cluster.isMaster) { const numCPUs = os.cpus().length; console.log(`Master process is running on PID: ${process.pid}`); // Fork workers (one for each CPU core) for (let i = 0; i < numCPUs; i++) { cluster.fork(); } // Listen for worker exit events cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died. Restarting...`); cluster.fork(); // Restart a new worker }); } else { // Worker processes http.createServer((req, res) => { res.writeHead(200); res.end('Hello from Node.js Cluster!\n'); }).listen(8000); console.log(`Worker process is running on PID: ${process.pid}`); }
説明:
この手法により、Node.js をマルチコア サーバー上で効果的に拡張できるようになります。
負荷分散は、Node.js アプリケーションの複数のインスタンス間で受信トラフィックを分散するために不可欠です。これにより、単一のサーバーが過負荷になることがなくなり、信頼性とパフォーマンスが向上します。
負荷分散を実装するにはさまざまな方法があります:
最も一般的で効率的な方法の 1 つは、NGINX のようなリバース プロキシを使用することです。負荷に基づいて、クライアント要求を利用可能な Node.js インスタンスの 1 つに転送します。
NGINX 構成の例:
upstream nodejs_servers { server 127.0.0.1:8000; server 127.0.0.1:8001; server 127.0.0.1:8002; } server { listen 80; location / { proxy_pass http://nodejs_servers; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
説明:
AWS、Google Cloud、Azure などのクラウド プロバイダーは、複数のインスタンス間でトラフィックを自動的に分散する組み込みの負荷分散サービスを提供します。
コンテナ (Docker など) とコンテナ オーケストレーション プラットフォーム (Kubernetes など) は、Node.js アプリケーションのスケーリングに広く使用されています。
Docker allows you to package your application into lightweight containers that can run consistently across different environments. By running multiple containers of your application, you can scale horizontally.
Kubernetes takes it a step further by automating the deployment, scaling, and management of your containerized applications. Kubernetes can dynamically scale the number of containers based on the current load.
Example: Scaling a Node.js Application with Kubernetes:
Create a Docker Image for Your Node.js App:
# Dockerfile for Node.js Application FROM node:14 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 8080 CMD ["node", "server.js"]
Deploy the Application on Kubernetes:
apiVersion: apps/v1 kind: Deployment metadata: name: nodejs-app spec: replicas: 3 selector: matchLabels: app: nodejs-app template: metadata: labels: app: nodejs-app spec: containers: - name: nodejs-app image: your-nodejs-app-image ports: - containerPort: 8080
Explanation:
Caching is a technique used to store frequently accessed data in memory, reducing the load on your application and improving response times.
Example: Using Redis for Caching in Node.js:
const redis = require('redis'); const client = redis.createClient(); const express = require('express'); const app = express(); // Cache middleware const cache = (req, res, next) => { const { id } = req.params; client.get(id, (err, data) => { if (err) throw err; if (data !== null) { res.send(JSON.parse(data)); // Serve cached data } else { next(); // Proceed to the next middleware } }); }; app.get('/data/:id', cache, (req, res) => { // Simulate fetching data from a database const data = { id: req.params.id, value: 'Some data' }; // Save data to Redis client.setex(req.params.id, 3600, JSON.stringify(data)); res.json(data); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
Explanation:
Use Asynchronous Code: Node.js is built around non-blocking, asynchronous code. Make sure all I/O operations are asynchronous to avoid blocking the event loop.
Leverage Microservices: Break down your application into smaller, manageable services that can be scaled independently.
Monitor Performance: Use tools like New Relic, Prometheus, or Datadog to monitor the performance of your application and scale dynamically based on traffic.
Optimize Resource Utilization: Use containerization (Docker, Kubernetes) and cloud-based services to optimize the utilization of resources, ensuring that your application scales efficiently.
Horizontal Scaling over Vertical: As your application grows, prioritize horizontal scaling over vertical scaling to distribute the load across multiple servers.
Scaling a Node.js application requires a well-thought-out strategy, including vertical and horizontal scaling, clustering, load balancing, caching, and monitoring. By leveraging these techniques, you can build a Node.js application that efficiently handles growing traffic and remains resilient under pressure. In this article, we've covered the core concepts and provided practical examples to guide you through the scaling process, enabling you to create scalable and reliable Node.js applications for production environments.
以上がNode.js アプリケーションのスケーリング: テクニックとベスト プラクティスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。