欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解如何在NodeJS應(yīng)用程序中處理多個(gè)API請(qǐng)求

 更新時(shí)間:2023年12月14日 08:33:06   作者:睡醒想錢(qián)錢(qián)  
NodeJS默認(rèn)是異步的,這意味著它已經(jīng)能夠同時(shí)處理多個(gè)請(qǐng)求,但它只適用于I/O操作,如HTTP請(qǐng)求、文件系統(tǒng)操作、數(shù)據(jù)庫(kù)查詢(xún)、實(shí)時(shí)聊天應(yīng)用等,在處理CPU密集型任務(wù)時(shí),可能需要很長(zhǎng)時(shí)間,這就是為什么NodeJS提供了一些我們將在下面介紹的特定包

Redis緩存

如果你有一組數(shù)據(jù)在加載應(yīng)用程序時(shí)經(jīng)常需要獲取,你可能希望將這些數(shù)據(jù)緩存起來(lái),而不是發(fā)送HTTP請(qǐng)求或運(yùn)行查詢(xún)。這就是為什么我建議你使用Redis。它非常簡(jiǎn)單易用。它基本上是另一個(gè)與主數(shù)據(jù)庫(kù)分開(kāi)的數(shù)據(jù)庫(kù),用于存儲(chǔ)所有緩存數(shù)據(jù)。

您需要在系統(tǒng)上安裝Redis,并可以使用以下代碼與Redis進(jìn)行交互。

user@username:/mnt/c/Users/HP$ sudo service redis-server start
user@username:/mnt/c/Users/HP$sudo service redis-server-start
user@username:/mnt/c/Users/HP$redis-cli
user@username:/mnt/c/Users/HP$set mykey "hello"
user@username:/mnt/c/Users/HP$get mykey

現(xiàn)在要在您的NodeJS應(yīng)用程序中使用它,您需要安裝redis包,并在名為redis.js的文件中創(chuàng)建一個(gè)redis客戶(hù)端的實(shí)例(您可以隨意命名)。

import redis from 'redis'

const PORT = process.env.REDIS_URL || 'redis://localhost:6379'

const client = redis.createClient({
    url: PORT
})

await client.connect()

client.on('error', (error) => {
    console.error('Redis client error:', error);
});

client.on('connect', (err) => {
    console.log('Connected to redis')
})

export default client

完成上述步驟后,您可以通過(guò)簡(jiǎn)單地編寫(xiě)以下代碼來(lái)導(dǎo)入客戶(hù)端并設(shè)置一個(gè)鍵

await client.set('mykey', 'hello')

節(jié)點(diǎn)緩存

這只是一個(gè)簡(jiǎn)單的緩存機(jī)制。在我們討論如何使用這個(gè)node-cache包之前,我們需要談?wù)劄槭裁催@與Redis緩存不同。

Node緩存是一個(gè)內(nèi)存緩存,而Redis緩存是存儲(chǔ)在“外部”的。這意味著,一旦您的節(jié)點(diǎn)應(yīng)用程序重新啟動(dòng),它將丟失其數(shù)據(jù)并且必須重新緩存。而Redis數(shù)據(jù)將存儲(chǔ)在網(wǎng)絡(luò)中,直到被刪除。Redis緩存也可以從另一個(gè)設(shè)備訪問(wèn),因?yàn)樗旧暇拖褚粋€(gè)數(shù)據(jù)庫(kù),但是node緩存只存在于特定的nodejs應(yīng)用程序中。除非您的nodejs應(yīng)用程序中有一個(gè)獲取路由來(lái)獲取緩存數(shù)據(jù)。

首先,安裝node-cache包并創(chuàng)建一個(gè)node-cache對(duì)象的實(shí)例來(lái)設(shè)置對(duì)象

import NodeCache from "node-cache"
const myCache = new NodeCache()

// to set one element
const success = myCache.set( "myKey", "hello");

// to set multiple elements
const obj = { my: "Special", variable: 42 };
const obj2 = { my: "other special", variable: 1337 };
 
const success = myCache.mset([
    {key: "myKey", val: obj, ttl: 10000},
    {key: "myKey2", val: obj2},
])

// to get the data
const value = myCache.get( "myKey" );

集群

通常,我們運(yùn)行一個(gè)單獨(dú)的NodeJS應(yīng)用程序,它將接收任何類(lèi)型的請(qǐng)求。想象一下,我們可以分別運(yùn)行大約8個(gè)副本的應(yīng)用程序,并放置一個(gè)負(fù)載均衡器,將請(qǐng)求分發(fā)到可用的應(yīng)用程序。這正是集群所做的事情!

與其他不同,這是一個(gè)內(nèi)置的NodeJS包,不需要您下載任何類(lèi)型的包。

需要注意的一點(diǎn)是,如果您運(yùn)行N個(gè)NodeJS應(yīng)用程序,數(shù)據(jù)不會(huì)在這些應(yīng)用程序之間共享。它們每個(gè)都以一個(gè)進(jìn)程ID獨(dú)立運(yùn)行。

讓我以一個(gè)基于express的應(yīng)用程序?yàn)槔?。通常我們做的是?/p>

const app = express()

const PORT = process.env.PORT || 5000

app.listen(PORT, () => console.log(`Server is running successfully on PORT ${PORT}`))

但是在運(yùn)行集群時(shí),您需要運(yùn)行N個(gè)這樣的服務(wù)器。(N代表系統(tǒng)中的CPU數(shù)量)

import cluster from 'cluster'

const numCpu = os.cpus().length

if(cluster.isPrimary){
    console.log(`Primary ${process.pid} is running`)
    for(let i=0; i<numCpu; i++){
        cluster.fork()
    }
    cluster.on('exit', (worker, code, signal) => {
        console.log(`${worker.process.pid} has exited`)
        cluster.fork()
    })
}else{
    app.listen(PORT, () => console.log(`Server ${process.pid} is running successfully on PORT ${PORT}`))
}

fork()函數(shù)是觸發(fā)新工作進(jìn)程的函數(shù),如果您注意到了,它會(huì)觸發(fā)fork()函數(shù)numCpu次。主工作進(jìn)程監(jiān)聽(tīng)所有連接,然后以輪詢(xún)方式將負(fù)載分配給其他工作進(jìn)程。“輪詢(xún)”只是指一種算法,它僅在一組可用資源/服務(wù)器之間分配任務(wù)。

工作線程

再次強(qiáng)調(diào),這是NodeJS提供的另一個(gè)內(nèi)置包。

首先,您需要了解NodeJS默認(rèn)是單線程的。單線程意味著您的Node應(yīng)用程序只有一個(gè)實(shí)例在運(yùn)行,即主線程。這個(gè)主線程接收所有請(qǐng)求并按順序執(zhí)行它們。這個(gè)主線程被稱(chēng)為“事件循環(huán)”。事件循環(huán)負(fù)責(zé)異步管理I/O操作,如網(wǎng)絡(luò)請(qǐng)求、文件操作和數(shù)據(jù)庫(kù)查詢(xún)。

現(xiàn)在這帶來(lái)了自己的優(yōu)勢(shì)和劣勢(shì)。當(dāng)單線程出現(xiàn)錯(cuò)誤時(shí),錯(cuò)誤處理變得困難,因?yàn)橹骶€程會(huì)崩潰。但如果是多線程,它確保只有發(fā)生錯(cuò)誤的線程崩潰,其余線程將繼續(xù)正常工作。

這就是為什么Node.js給我們提供了一個(gè)名為worker-threads的包的選項(xiàng),它可以幫助我們將單線程的Node應(yīng)用程序轉(zhuǎn)換為多線程應(yīng)用程序。讓我們看看如何在我們的應(yīng)用程序中實(shí)現(xiàn)這一點(diǎn):

 主線程(calc.js):

import { Worker, workerData } from "worker_threads"
const makeCalculation = async (req, res) => {
    try {
        const worker = new Worker('./worker.js', {
            workerData: {
                num: 10
            }
        })
        worker.on('message', (message) => {
            if(message.success){
                res.send({message: 'Successfully calculated', success: true, ans: message.ans})
            }else{
                res.send({message: 'Calculation not possible', success: false})
            }
        })
    } catch (error) {
        console.log('Error 7: ', error)
    }
  }

export default makeCalculation;

工作線程(worker.js):

import { parentPort, workerData } from 'worker_threads';

const ans = workerData.num*10

parentPort.postMessage({message: 'Successfully calculated', success: true, ans: ans})

這樣的工作方式是,在主線程上,我們使用Worker()函數(shù)創(chuàng)建一個(gè)新的工作線程,該函數(shù)接受一個(gè)文件名作為參數(shù)。我們還向該文件傳遞數(shù)據(jù),這些數(shù)據(jù)可以通過(guò)workerData對(duì)象訪問(wèn)。因此,主線程等待來(lái)自工作線程的消息事件,這樣可以很容易地避免在工作線程中出現(xiàn)任何錯(cuò)誤時(shí)導(dǎo)致應(yīng)用程序崩潰。

微服務(wù)架構(gòu)

通常我們使用的是單體架構(gòu),這在一定程度上是可以的。但是在某個(gè)階段,一些項(xiàng)目會(huì)涉及到多個(gè)表、數(shù)據(jù)庫(kù)等,這種架構(gòu)已經(jīng)無(wú)法滿(mǎn)足需求。這就是微服務(wù)概念誕生的原因。

顧名思義,多個(gè)服務(wù)被創(chuàng)建來(lái)執(zhí)行特定的任務(wù),這些服務(wù)相互連接?;旧希覀冋诜职l(fā)應(yīng)用程序,每個(gè)應(yīng)用程序負(fù)責(zé)在特定主題上執(zhí)行一組特定的操作。

舉個(gè)例子,想象一下你要?jiǎng)?chuàng)建一個(gè)類(lèi)似滴滴的應(yīng)用。你可能會(huì)在單個(gè)數(shù)據(jù)庫(kù)中為用戶(hù)和司機(jī)各創(chuàng)建一個(gè)表。這是普通開(kāi)發(fā)者的做法。但是對(duì)于滴滴及其龐大的網(wǎng)絡(luò)來(lái)說(shuō),這種方法行不通。這就是為什么他們需要一個(gè)專(zhuān)門(mén)負(fù)責(zé)用戶(hù)的nodejs應(yīng)用,另一個(gè)專(zhuān)門(mén)負(fù)責(zé)司機(jī)的應(yīng)用。在某些情況下,它們可能會(huì)進(jìn)一步分成更多的應(yīng)用。需要注意的是,用戶(hù)和司機(jī)的整個(gè)數(shù)據(jù)庫(kù)也必須分別創(chuàng)建。

現(xiàn)在設(shè)計(jì)這樣的架構(gòu)可能會(huì)導(dǎo)致問(wèn)題,如數(shù)據(jù)不一致、服務(wù)間通信、部署管理等,這些都應(yīng)在實(shí)施之前考慮到。因此,需要非常謹(jǐn)慎的設(shè)計(jì)和觀察來(lái)完成這項(xiàng)工作。

實(shí)現(xiàn)這一點(diǎn)的方法很簡(jiǎn)單,只需創(chuàng)建兩個(gè)運(yùn)行在不同端口上的不同應(yīng)用程序:

users.js

const express = require('express');
const app = express();

app.listen(3000, () => {
  console.log('Users service is running on port 3000');
});

drivers.js

const express = require('express');
const app = express();

app.listen(4000, () => {
  console.log('Drivers service is running on port 3000');
});

Redis Lock

正如我所說(shuō),Redis提供了許多服務(wù),鎖就是其中之一。

首先,當(dāng)您想要防止可能導(dǎo)致死鎖的情況發(fā)生時(shí),就會(huì)使用鎖。這種情況發(fā)生在您想要運(yùn)行進(jìn)程A,而該進(jìn)程需要使用另一個(gè)正在運(yùn)行的進(jìn)程B返回的數(shù)據(jù)時(shí)。因此,進(jìn)程A必須等待進(jìn)程B完成后才能繼續(xù)。

為了實(shí)現(xiàn)這一點(diǎn),我們使用Redis Lock。當(dāng)進(jìn)程B啟動(dòng)時(shí),它會(huì)獲取一個(gè)鎖,直到它的工作完成,它將保持鎖定。只有在執(zhí)行完成后,它才會(huì)釋放鎖?,F(xiàn)在進(jìn)程A可以恢復(fù)其工作。

讓我們?cè)诖a中看看這個(gè),這可能會(huì)讓你更好地理解:

import redis from 'redis'
const client = redis.createClient();

function processA() {
  client.set('my_lock', 'locked', 'NX', 'EX', 10, (error, result) => {
    if (result === 'OK') {
      console.log('Function A is executing...');
      
      setTimeout(() => {
        client.del('my_lock', (error, result) => {
          console.log('Lock released by Function A.');
        });
      }, 5000); 
      
    } else {
      console.log('Function A is waiting for the lock...');
      setTimeout(functionA, 1000); 
    }
  });
}

function processB() {
  client.set('my_lock', 'locked', 'NX', 'EX', 10, (error, result) => {
    if (result === 'OK') {
      console.log('Function B is executing...');
   
      setTimeout(() => {
        client.del('my_lock', (error, result) => {
          console.log('Lock released by Function B.');
        });
      }, 3000); 
      
    } else {
      console.log('Function B is waiting for the lock...');
      setTimeout(functionB, 1000); 
    }
  });
}

processA();
processB();

所以這里我正在運(yùn)行processA()和processB()。一旦processA()開(kāi)始,它就使用set()函數(shù)設(shè)置一個(gè)鎖。

“NX”代表“不存在”。它確保只有在鎖不存在時(shí)才設(shè)置鎖。“EX”代表“過(guò)期”。10確定了鎖將被設(shè)置的秒數(shù)。

由于processA()已經(jīng)獲取了鎖,processB()中的結(jié)果將為null,因此它將無(wú)法執(zhí)行其任務(wù)并開(kāi)始等待。

注意:默認(rèn)情況下,Javascript是單線程的,因此每個(gè)函數(shù)按順序執(zhí)行。這意味著在這個(gè)例子中,無(wú)論鎖是否被獲取,processB()都只會(huì)在processA()完成后執(zhí)行。因此,要完全理解Redis鎖的用例,您必須在應(yīng)用程序中擁有分布式實(shí)例。想象一下在不同的應(yīng)用程序上運(yùn)行processA()和processB()。這才是您實(shí)際需要實(shí)現(xiàn)這一功能的時(shí)候。

總結(jié)一下..

我們已經(jīng)簡(jiǎn)單了解了Redis緩存、Node緩存、集群、工作線程、微服務(wù)架構(gòu)和Redis鎖。這篇文章中寫(xiě)的只是簡(jiǎn)單的介紹和使用,如果想要深入了解,請(qǐng)參考官方文檔。

以上就是詳解如何在NodeJS應(yīng)用程序中處理多個(gè)API請(qǐng)求的詳細(xì)內(nèi)容,更多關(guān)于NodeJS中處理多個(gè)API請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • node.js 發(fā)布訂閱模式的實(shí)例

    node.js 發(fā)布訂閱模式的實(shí)例

    下面小編就為大家?guī)?lái)一篇node.js 發(fā)布訂閱模式的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就想給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • Mac node刪除以及重新安裝案例詳解

    Mac node刪除以及重新安裝案例詳解

    這篇文章主要介紹了Mac node刪除以及重新安裝案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 在Mac下徹底卸載node和npm的方法

    在Mac下徹底卸載node和npm的方法

    今天小編就為大家分享一篇在Mac下徹底卸載node和npm的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • Node.js查詢(xún)MySQL并返回結(jié)果集給客戶(hù)端的全過(guò)程

    Node.js查詢(xún)MySQL并返回結(jié)果集給客戶(hù)端的全過(guò)程

    nodejs最大的優(yōu)勢(shì)也是大家用著最為難以理解的一點(diǎn),就是它的異步功能,它幾乎所有的io操作都是異步的,這也就導(dǎo)致很多人不理解也用不習(xí)慣,下面這篇文章主要給大家介紹了關(guān)于Node.js查詢(xún)MySQL并返回結(jié)果集給客戶(hù)端的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • Node.js 中 morgan 依賴(lài)及基本使用詳解

    Node.js 中 morgan 依賴(lài)及基本使用詳解

    文章介紹了Node.js中`morgan`依賴(lài)的安裝、基本使用、日志格式(如`dev`、`combined`、`common`等),以及如何自定義日志格式和將日志寫(xiě)入文件,感興趣的朋友一起看看吧
    2025-02-02
  • NodeJS中配置請(qǐng)求代理服務(wù)器方式

    NodeJS中配置請(qǐng)求代理服務(wù)器方式

    這篇文章主要介紹了NodeJS中配置請(qǐng)求代理服務(wù)器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 詳解nodejs微信公眾號(hào)開(kāi)發(fā)——4.自動(dòng)回復(fù)各種消息

    詳解nodejs微信公眾號(hào)開(kāi)發(fā)——4.自動(dòng)回復(fù)各種消息

    這篇文章主要介紹了詳解nodejs微信公眾號(hào)開(kāi)發(fā)——4.自動(dòng)回復(fù)各種消息,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-04-04
  • Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用詳解

    Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用詳解

    node-schedule是 Node.js 的一個(gè)定時(shí)任務(wù)(crontab)模塊。這篇文章主要介紹了Node.js設(shè)置定時(shí)任務(wù)之node-schedule模塊的使用,需要的朋友可以參考下
    2020-04-04
  • Nodejs中JSON和YAML互相轉(zhuǎn)換方式

    Nodejs中JSON和YAML互相轉(zhuǎn)換方式

    這篇文章主要介紹了Nodejs中JSON和YAML互相轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Node.js筆記之process模塊解讀

    Node.js筆記之process模塊解讀

    這篇文章主要介紹了Node.js process模塊解讀,process存在于全局對(duì)象上,不需要使用require()加載即可使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05

最新評(píng)論