Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

青灯夜游
Lepaskan: 2022-07-12 20:36:58
ke hadapan
2527 orang telah melayarinya

Benang dan proses ialah konsep asas sistem pengendalian komputer dan merupakan perkataan frekuensi tinggi dalam kalangan pengaturcara. Apakah proses dan urutan dalam Nod? Mari ketahui lebih lanjut mengenai perkara ini dalam artikel ini, saya harap ia akan membantu semua orang!

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

1 Proses dan rangkaian

1.1 Definisi teks profesional

  • Proses ), a. proses adalah aktiviti menjalankan program dalam komputer pada set data tertentu Ia adalah unit asas peruntukan sumber dan penjadualan dalam sistem.
  • Benang (Thread), utas ialah unit terkecil yang sistem pengendalian boleh melakukan penjadualan pengiraan Ia termasuk dalam proses dan merupakan unit operasi sebenar dalam proses.

1.2 Pemahaman popular

Penerangan di atas agak sukar, dan anda mungkin tidak memahaminya selepas membacanya, dan ia tidak kondusif untuk memahami dan ingatan. Jadi mari kita ambil contoh mudah:

Katakan anda seorang budak di tapak penghantaran ekspres tertentu Pada mulanya, laman web ini bertanggungjawab untuk tidak ramai penduduk di kawasan itu, dan anda seorang sahaja yang mengumpul bungkusan itu . Selepas menghantar bungkusan ke rumah Zhang San, dan kemudian pergi ke rumah Li Si untuk mengambilnya, perkara perlu dilakukan satu persatu Ini dipanggil utas tunggal, dan semua kerja mesti dilakukan dengan teratur .

Kemudian, terdapat lebih ramai penduduk di kawasan ini, dan tapak menugaskan berbilang lelaki dan ketua pasukan ke kawasan ini ketua kumpulan ialah benang utama, dan setiap saudara ialah benang. Alat seperti troli yang digunakan oleh tapak penghantaran ekspres disediakan oleh tapak dan boleh digunakan oleh semua orang, bukan hanya untuk satu orang Ini dipanggil

perkongsian sumber berbilang benang.

Pada masa ini hanya terdapat satu troli tapak dan semua orang perlu menggunakannya. Ini dipanggil

konflik

. Terdapat banyak cara untuk menyelesaikan masalah, seperti menunggu dalam barisan atau menunggu pemberitahuan apabila lelaki lain selesai. Ini dipanggil penyegerakan benang.

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?Ibu pejabat mempunyai banyak tapak, dan model operasi setiap tapak adalah hampir sama. Ini dipanggil

berbilang proses

. Ibu pejabat dipanggil proses utama, dan setiap tapak dipanggil proses kanak-kanak. Antara ibu pejabat dan tapak, serta antara setiap tapak, troli adalah bebas antara satu sama lain dan tidak boleh dicampur Ini dipanggil sumber tidak dikongsi antara proses
. Tapak boleh berkomunikasi antara satu sama lain melalui panggilan telefon, dsb. Ini dipanggil talian paip. Terdapat cara kerjasama lain antara tapak untuk memudahkan penyiapan tugas pengkomputeran yang lebih besar, yang dipanggil penyegerakan antara proses. Anda juga boleh melihat penjelasan ringkas Ruan Yifeng tentang proses dan urutan.

2. Proses dan urutan dalam Node.js

Node.js

ialah perkhidmatan satu utas, dipacu peristiwa dan tidak menyekat I/O Ciri bahasa model menjadikan Node.js cekap dan ringan. Kelebihannya ialah ia mengelakkan penukaran benang yang kerap dan konflik sumber; ia bagus pada operasi intensif I/O (modul asas libuv memanggil keupayaan I/O tak segerak yang disediakan oleh sistem pengendalian melalui berbilang benang untuk melaksanakan pelbagai tugas) , tetapi untuk Node.js pada bahagian pelayan , mungkin terdapat ratusan permintaan yang perlu diproses sesaat Apabila menghadapi permintaan intensif CPU, kerana ia adalah mod satu benang, ia pasti akan menyebabkan penyekatan.

2.1. Penyekatan Node.js

Kami menggunakan Koa untuk membina perkhidmatan Web dan menggunakan kaedah jujukan Fibonacci untuk mensimulasikan Jenis pemprosesan intensif CPU Node.js tugas pengiraan:

Jujukan Fibonacci, juga dikenali sebagai jujukan bahagian emas, jujukan ini bermula dari item ketiga, setiap item adalah sama dengan jumlah dua item sebelumnya: 0, 1, 1, 2, 3 , 5, 8, 13, 21,...

Laksanakan
// app.js
const Koa = require('koa')
const router = require('koa-router')()
const app = new Koa()

// 用来测试是否被阻塞
router.get('/test', (ctx) => {
    ctx.body = {
        pid: process.pid,
        msg: 'Hello World'
    }
})
router.get('/fibo', (ctx) => {
    const { num = 38 } = ctx.query
    const start = Date.now()
    // 斐波那契数列
    const fibo = (n) => {
        return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1
    }
    fibo(num)

    ctx.body = {
        pid: process.pid,
        duration: Date.now() - start
    }
})

app.use(router.routes())
app.listen(9000, () => {
    console.log('Server is running on 9000')
})
Salin selepas log masuk
Mulakan perkhidmatan dan gunakan Posmen untuk menghantar permintaan Anda dapat melihat bahawa 38 pengiraan mengambil masa 617ms. utas utama Node.js telah disekat selama lebih daripada 600 milisaat kerana tugas pengkomputeran intensif CPU telah dilakukan. Jika lebih banyak permintaan diproses pada masa yang sama, atau tugas pengiraan lebih kompleks, maka semua permintaan selepas permintaan ini akan ditangguhkan.

node app.js

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js? Mari buat axios.js baharu untuk mensimulasikan penghantaran berbilang permintaan Pada masa ini, tukar bilangan pengiraan fibo dalam app.js kepada 43 , digunakan untuk mensimulasikan tugas pengkomputeran yang lebih kompleks:

// axios.js
const axios = require('axios')

const start = Date.now()
const fn = (url) => {
    axios.get(`http://127.0.0.1:9000/${ url }`).then((res) => {
        console.log(res.data, `耗时: ${ Date.now() - start }ms`)
    })
}

fn('test')
fn('fibo?num=43')
fn('test')
Salin selepas log masuk

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js? Ia boleh dilihat apabila permintaan perlu melaksanakan tugas pengkomputeran intensif CPU , Permintaan seterusnya disekat dan menunggu Jika terdapat terlalu banyak permintaan sedemikian, perkhidmatan itu pada dasarnya akan disekat. Untuk kekurangan ini, Node.js telah menebusnya.

2.2、master-worker

master-worker 模式是一种并行模式,核心思想是:系统有两个及以上的进程或线程协同工作时,master 负责接收和分配并整合任务,worker 负责处理任务。

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

2.3、多线程

线程是 CPU 调度的一个基本单位,只能同时执行一个线程的任务,同一个线程也只能被一个 CPU 调用。如果使用的是多核 CPU,那么将无法充分利用 CPU 的性能。

多线程带给我们灵活的编程方式,但是需要学习更多的 Api 知识,在编写更多代码的同时也存在着更多的风险,线程的切换和锁也会增加系统资源的开销。

  • worker_threads 工作线程,给 Node.js 提供了真正的多线程能力。

worker_threads 是 Node.js 提供的一种多线程 Api。对于执行 CPU 密集型的计算任务很有用,对 I/O 密集型的操作帮助不大,因为 Node.js 内置的异步 I/O 操作比 worker_threads 更高效。worker_threads 中的 Worker,parentPort 主要用于子线程和主线程的消息交互。

将 app.js 稍微改动下,将 CPU 密集型的计算任务交给子线程计算:

// app.js
const Koa = require('koa')
const router = require('koa-router')()
const { Worker } = require('worker_threads')
const app = new Koa()

// 用来测试是否被阻塞
router.get('/test', (ctx) => {
    ctx.body = {
        pid: process.pid,
        msg: 'Hello World'
    }
})
router.get('/fibo', async (ctx) => {
    const { num = 38 } = ctx.query
    ctx.body = await asyncFibo(num)
})

const asyncFibo = (num) => {
    return new Promise((resolve, reject) => {
        // 创建 worker 线程并传递数据
        const worker = new Worker('./fibo.js', { workerData: { num } })
        // 主线程监听子线程发送的消息
        worker.on('message', resolve)
        worker.on('error', reject)
        worker.on('exit', (code) => {
            if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`))
        })
    })
}

app.use(router.routes())
app.listen(9000, () => {
    console.log('Server is running on 9000')
})
Salin selepas log masuk

新增 fibo.js 文件,用来处理复杂计算任务:

const { workerData, parentPort } = require('worker_threads')
const { num } = workerData

const start = Date.now()
// 斐波那契数列
const fibo = (n) => {
    return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1
}
fibo(num)

parentPort.postMessage({
    pid: process.pid,
    duration: Date.now() - start
})
Salin selepas log masuk

执行上文的 axios.js,此时将 app.js 中的 fibo 计算次数改为 43,用来模拟更复杂的计算任务:

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

可以看到,将 CPU 密集型的计算任务交给子线程处理时,主线程不再被阻塞,只需等待子线程处理完成后,主线程接收子线程返回的结果即可,其他请求不再受影响。
上述代码是演示创建 worker 线程的过程和效果,实际开发中,请使用线程池来代替上述操作,因为频繁创建线程也会有资源的开销。

线程是 CPU 调度的一个基本单位,只能同时执行一个线程的任务,同一个线程也只能被一个 CPU 调用。

我们再回味下,本小节开头提到的线程和 CPU 的描述,此时由于是新的线程,可以在其他 CPU 核心上执行,可以更充分的利用多核 CPU。

2.4、多进程

Node.js 为了能充分利用 CPU 的多核能力,提供了 cluster 模块,cluster 可以通过一个父进程管理多个子进程的方式来实现集群的功能。

  • child_process 子进程,衍生新的 Node.js 进程并使用建立的 IPC 通信通道调用指定的模块。
  • cluster 集群,可以创建共享服务器端口的子进程,工作进程使用 child_process 的 fork 方法衍生。

cluster 底层就是 child_process,master 进程做总控,启动 1 个 agent 进程和 n 个 worker 进程,agent 进程处理一些公共事务,比如日志等;worker 进程使用建立的 IPC(Inter-Process Communication)通信通道和 master 进程通信,和 master 进程共享服务端口。

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

新增 fibo-10.js,模拟发送 10 次请求:

// fibo-10.js
const axios = require('axios')

const url = `http://127.0.0.1:9000/fibo?num=38`
const start = Date.now()

for (let i = 0; i  {
        console.log(res.data, `耗时: ${ Date.now() - start }ms`)
    })
}
Salin selepas log masuk

可以看到,只使用了一个进程,10 个请求慢慢阻塞,累计耗时 15 秒:

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

接下来,将 app.js 稍微改动下,引入 cluster 模块:

// app.js
const cluster = require('cluster')
const http = require('http')
const numCPUs = require('os').cpus().length
// const numCPUs = 10 // worker 进程的数量一般和 CPU 核心数相同
const Koa = require('koa')
const router = require('koa-router')()
const app = new Koa()

// 用来测试是否被阻塞
router.get('/test', (ctx) => {
    ctx.body = {
        pid: process.pid,
        msg: 'Hello World'
    }
})
router.get('/fibo', (ctx) => {
    const { num = 38 } = ctx.query
    const start = Date.now()
    // 斐波那契数列
    const fibo = (n) => {
        return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1
    }
    fibo(num)

    ctx.body = {
        pid: process.pid,
        duration: Date.now() - start
    }
})
app.use(router.routes())

if (cluster.isMaster) {
    console.log(`Master ${process.pid} is running`)
    
    // 衍生 worker 进程
    for (let i = 0; i  {
        console.log(`worker ${worker.process.pid} died`)
    })
} else {
    app.listen(9000)
    console.log(`Worker ${process.pid} started`)
}
Salin selepas log masuk

执行 node app.js 启动服务,可以看到,cluster 帮我们创建了 1 个 master 进程和 4 个 worker 进程:

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

通过 fibo-10.js  模拟发送 10 次请求,可以看到,四个进程处理 10 个请求耗时近 9 秒:

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

当启动 10 个 worker 进程时,看看效果:

Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?

Ia hanya mengambil masa kurang daripada 3 saat, tetapi bilangan proses tidak terhad. Dalam pembangunan harian, bilangan proses pekerja secara amnya sama dengan bilangan teras CPU.

2.5. Penerangan berbilang proses

Mendayakan pelbagai proses bukan sepenuhnya untuk menangani konkurensi yang tinggi, tetapi untuk menyelesaikan masalah penggunaan CPU berbilang teras yang tidak mencukupi Node.js.
Proses anak yang diperoleh daripada proses induk melalui kaedah fork mempunyai sumber yang sama seperti proses induk, tetapi ia bebas dan tidak berkongsi sumber antara satu sama lain. Bilangan proses biasanya ditetapkan berdasarkan bilangan teras CPU kerana sumber sistem adalah terhad.

3. Ringkasan

1 Kebanyakan penyelesaian untuk tugasan pengkomputeran intensif CPU boleh digantikan dengan penyelesaian berbilang proses; Node.js adalah asynchronous, ini tidak bermakna ia tidak akan menyekat Sebaik-baiknya jangan memproses tugasan intensif CPU dalam utas utama untuk memastikan kelancaran aliran utama
3. Jangan mengejar secara membabi buta prestasi tinggi dan keselarasan tinggi, dan memenuhi keperluan sistem Walau bagaimanapun, kecekapan dan ketangkasan adalah keperluan projek, yang juga merupakan ciri ringan Node.js.
4. Terdapat banyak konsep proses dan urutan dalam Node.js yang disebut dalam artikel tetapi tidak dibincangkan secara terperinci atau tidak disebut, seperti: libuv Node.js asas I/O, saluran komunikasi IPC, dsb. Cara melindungi proses, cara mengendalikan tugas berjadual tanpa berkongsi sumber antara proses, proses ejen, dsb.
5 Kod di atas boleh dilihat di https://github.com/liuxy0551/node-process- benang.

Untuk lebih banyak pengetahuan berkaitan nod, sila lawati:

tutorial nodejs!

Atas ialah kandungan terperinci Bagaimana untuk memahami proses dan benang? Apakah proses dan utas dalam Node.js?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:segmentfault.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan