I/O 到底有什么效果和为什么能提高并发处理能力?

Node.js 不善于处理 CPU 密集型的业务,就会导致性能问题,如果要实现一个耗时 CPU 的计算逻辑,处理方法有 2 种:

  • 直接在主业务流程中处理;
  • 通过网络异步 I/O 给其他进程处理。

目标 : 分别计算从 0 到 1000000000 之间的和

| |

主流程执行

|

异步网络 I/O

| | —- | —- | —- | | 耗时 | 1.100s | 0.575s |

原因:
异步网络 I/O 充分利用了 Node.js 的异步事件驱动能力,将耗时 CPU 计算逻辑给到其他进程来处理,而无须等待耗时 CPU 计算,可以直接处理其他请求或者其他部分逻辑。第一种同步执行的方式就无法去处理其逻辑,导致性能受到影响。

执行1

  1. const http = require('http');
  2. /**
  3. *
  4. * 创建 http 服务,简单返回
  5. */
  6. const server = http.createServer((req, res) => {
  7. res.write(`${startCount() + nextCount()}`);
  8. res.end();
  9. });
  10. /**
  11. * 从 0 计算到 500000000 的和
  12. */
  13. function startCount() {
  14. let sum = 0;
  15. for (let i = 0; i < 500000000; i++) {
  16. sum = sum + i;
  17. }
  18. return sum;
  19. }
  20. /**
  21. * 从 500000000 计算到 1000000000 之间的和
  22. */
  23. function nextCount() {
  24. let sum = 0;
  25. for (let i = 500000000; i < 1000000000; i++) {
  26. sum = sum + i;
  27. }
  28. return sum;
  29. }
  30. /**
  31. *
  32. * 启动服务
  33. */
  34. server.listen(4000, () => {
  35. console.log('server start http://127.0.0.1:4000');
  36. });

启动服务, 访问http://127.0.0.1:4000

执行2

需要安装, yarn add request-promise
node index.js

  1. // index.js
  2. const http = require('http');
  3. const rp = require('request-promise');
  4. /**
  5. *
  6. * 创建 http 服务,简单返回
  7. */
  8. const server = http.createServer((req, res) => {
  9. Promise.all([startCount(), nextCount()]).then((values) => {
  10. let sum = values.reduce(function (prev, curr, idx, arr) {
  11. return parseInt(prev) + parseInt(curr);
  12. });
  13. res.write(`${sum}`);
  14. res.end();
  15. });
  16. });
  17. /**
  18. * 从 0 计算到 500000000 的和
  19. */
  20. async function startCount() {
  21. return await rp.get('http://127.0.0.1:4001');
  22. }
  23. /**
  24. * 从 500000000 计算到 1000000000 之间的和
  25. */
  26. async function nextCount() {
  27. return await rp.get('http://127.0.0.1:4002');
  28. }
  29. /**
  30. *
  31. * 启动服务
  32. */
  33. server.listen(4000, () => {
  34. console.log('server start http://127.0.0.1:4000');
  35. });

node startServer.js

  1. // startServer.js
  2. const http = require('http');
  3. /**
  4. *
  5. * 创建 http 服务,简单返回
  6. */
  7. const server = http.createServer((req, res) => {
  8. let sum = 0;
  9. for(let i=0; i<500000000; i++){
  10. sum = sum + i;
  11. }
  12. res.write(`${sum}`);
  13. res.end();
  14. });
  15. /**
  16. *
  17. * 启动服务
  18. */
  19. server.listen(4001, () => {
  20. console.log('server start http://127.0.0.1:4001');
  21. });

node nextServer.js

  1. const http = require('http');
  2. /**
  3. *
  4. * 创建 http 服务,简单返回
  5. */
  6. const server = http.createServer((req, res) => {
  7. let sum = 0;
  8. for (let i = 500000000; i < 1000000000; i++) {
  9. sum = sum + i;
  10. }
  11. res.write(`${sum}`);
  12. res.end();
  13. });
  14. /**
  15. *
  16. * 启动服务
  17. */
  18. server.listen(4002, () => {
  19. console.log('server start http://127.0.0.1:4002');
  20. });

访问 http://127.0.0.1:4000/