V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yamada
V2EX  ›  Node.js

crypto 里的部分加解密函数为啥是同步的?

  •  
  •   yamada · 2016-06-29 17:48:07 +08:00 · 3767 次点击
    这是一个创建于 2857 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如 crypto.publicEncrypt 、 crypto.privateDecrypt ,这种比较耗时的函数为啥是同步的而不是异步回调?不会卡住整个进程么万一调用的次数比较多的话

    32 条回复    2016-07-10 17:29:48 +08:00
    clino
        1
    clino  
       2016-06-29 17:58:00 +08:00
    问题是 nodejs 是多线程的吗?
    ncisoft
        2
    ncisoft  
       2016-06-29 18:04:20 +08:00 via Android
    linux 系统调用也大多是同步的
    2225377fjs
        3
    2225377fjs  
       2016-06-29 18:04:26 +08:00   ❤️ 6
    为什么要异步。。?加密解密本来就是 CPU 运算,又不是 IO ,有等待, CPU 空闲出来了,所以做成异步,让 CPU 做别的事情去。。。加解密的时候 CPU 本来就没空闲,难道将加密解密的运算派发到别的并行线程去做,强行做成异步的?这样有啥好处?又不能提高整个系统的吞吐量。
    何为卡主整个进程?如果因为 IO 之类的等待,整个执行过程被挂起,这个才叫卡住了。加解密的时候执行线程就一直在运算,何来卡主整个进程而言。?
    (感觉楼主还需要学习一些基本概念)
    yamada
        4
    yamada  
    OP
       2016-06-29 18:08:28 +08:00
    @2225377fjs 想明白了, CPU 密集运算确实不需要异步
    billlee
        5
    billlee  
       2016-06-29 19:48:01 +08:00
    @clino node.js 是真是多线程的,你可以 ps -eL 看一下。异步磁盘 IO, 应该用多线程模拟的吧
    edsgerlin
        6
    edsgerlin  
       2016-06-29 20:54:44 +08:00
    @2225377fjs 其实强行做成异步也不是不行。
    CRVV
        7
    CRVV  
       2016-06-29 21:50:22 +08:00
    @2225377fjs 照你这么说为啥从 redis 取数据要做成异步的?
    ChiChou
        8
    ChiChou  
       2016-06-29 21:51:37 +08:00
    @CRVV 从 redis 取数据是从 socket 读取的,属于 I/O 操作了
    CRVV
        9
    CRVV  
       2016-06-29 22:03:07 +08:00
    @yamada
    crypto.pbkdf2 是异步的
    异步的用着麻烦,而且增加函数调用的开销。同步的当然会影响性能
    所以有个权衡的,所以 pbkdf2 还有个 pbkdf2Sync ,让用户根据情况选择用不用异步

    这事和是不是 CPU 密集根本没有关系
    CRVV
        10
    CRVV  
       2016-06-29 22:10:09 +08:00
    @ChiChou redis 这个例子的确不对
    其实 crypto 里到处都是 CPU 密集的异步的例子, Cipher 、 Hash 之类的
    yamada
        11
    yamada  
    OP
       2016-06-29 22:37:13 +08:00
    @CRVV 看了下文档, hash 是同步啊, crypto 里只有 crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)和 crypto.randomBytes(size[, callback])是异步
    billlee
        12
    billlee  
       2016-06-29 22:51:47 +08:00
    @yamada hash 支持 stream 接口,这算是异步了吧。不过 CPU 密集用异步确实没意义,徒增开销。
    abcdabcd987
        13
    abcdabcd987  
       2016-06-29 23:03:07 +08:00
    @billlee 我觉得还是有意义的,新开一个 worker ,把计算任务丢进去,发挥多核优势?
    magicdawn
        14
    magicdawn  
       2016-06-29 23:13:23 +08:00
    终于有人提了...随便用一下 hash / hmac / Cipher / Decipher 都会 stop the world ...
    对于服务端能容忍么...不能哎
    shyling
        15
    shyling  
       2016-06-30 00:21:31 +08:00
    如果是 pure js 实现的话,同步无可厚非。。如果是 c/c++的话,交给 worker thread 回调貌似更好一点。很多计算也不一定能用到多核,如果能够不影响 v8 线程感觉也是不错的,毕竟处理器不仅仅有(完全空闲,完全占满) 2 种状态。不过具体的就不知道了。。
    CupTools
        16
    CupTools  
       2016-06-30 05:44:20 +08:00
    @2225377fjs “不能再同意更多”
    haozhang
        17
    haozhang  
       2016-06-30 08:47:10 +08:00 via iPhone
    我猜同步的那几个 api 是将任务下发给底层 c++,然后 js 运行时的线程阻塞等待底层加密的结果,而异步 api 不会造成 js 线程的阻塞。
    yamada
        18
    yamada  
    OP
       2016-06-30 09:52:53 +08:00 via Android
    仔细想了下, cpu 密集运算异步也是有意义的,假如有个 cpu 密集运算函数,在同步下要耗时 1000ms ,同时会 stop the world ,在异步下要耗时 1500ms ,但可以把 cpu 分给其他任务使用,那我宁愿选择后者,毕竟假如没有其他任务的时候,异步耗时也只会有 1050ms
    clino
        19
    clino  
       2016-06-30 09:59:09 +08:00
    @yamada 所以关键还是是否多线程啊,多线程才能利用到多核
    yamada
        20
    yamada  
    OP
       2016-06-30 10:08:48 +08:00 via Android
    @clino 这里不谈多核问题,这和单核多核没关系,就算单核,我也是愿意让 cpu 运算函数执行时间变长,把 cpu 时间分给其他任务
    clino
        21
    clino  
       2016-06-30 10:13:06 +08:00
    @yamada 那也需要多线程,否则也做不到你说的"让 cpu 运算函数执行时间变长,把 cpu 时间分给其他任务"
    需要开新线程跑 cpu 密集型任务
    yamada
        22
    yamada  
    OP
       2016-06-30 10:13:39 +08:00 via Android
    @2225377fjs
    如果因为 IO 之类的等待,整个执行过程被挂起,这个才叫卡住了。加解密的时候执行线程就一直在运算,何来卡主整个进程而言。?

    你就把加解密一直在运算当做等待好了,那不就是卡住了整个进程么?我希望能异步运算,这样就还能处理其他任务,就算会降低性能,我仍然希望如此
    yamada
        23
    yamada  
    OP
       2016-06-30 10:17:15 +08:00 via Android
    @clino 可不可以把异步假设为"开新线程来执行"?我不懂 nodejs 的异步原理,刚学,说到底 nodejs 不适合干这种活,我还是用其他的方法来加解密吧
    clino
        24
    clino  
       2016-06-30 10:21:57 +08:00 via Android
    @yamada 异步不一定非要开新线程,但是 cpu 密集型的你不开新线程做的话 效果跟同步是一样的
    这个跟语言没关系,因为一个 cpu 核同时只能跑一个线程
    2225377fjs
        25
    2225377fjs  
       2016-06-30 10:49:50 +08:00
    @abcdabcd987
    @yamada
    @haozhang
    @billlee
    充分利用系统资源,提高真个系统吞吐量, node 的并行是通过多进程来实现的, libuv 确实也有多线程,但是这只是为了做磁盘 IO 做的(印象中好像还有 DNS 的一些操作),而不是用来跑任务,用并行多线程确实可以将运算交给另外一个线程,这样来做成异步的,但是 node 的多线程可不是为了这个存在的。
    对于纯异步,多进程的系统,例如 nodejs ,单个进程中再引入并行的多线程来执行 CPU 运算,并不能提高系统的吞吐量,反而会引入其他的问题,对于负载很高的时候,更应该做的是如何将各个任务分布到各个 worker 进程来做,从而利用 CPU 资源。
    也有多进程的系统也引入了多线程,例如 Nginx 之类的,但是他们的 IOLoop 和主逻辑也还是在同一个线程中执行的,这些引入的其他线程更多的是为隔离上层代码的阻塞,例如 Nginx 去同步的请求外部的系统,上层一些逻辑不得不阻塞, upstream 配套起来用。

    上面很多说的通过开多个线程,提高系统性能啥的,这个不是 Node 的系统模型,而是 Java 环境下的模型,人家是单进程多线程。

    而且正确的实现多线程程序不是那么简单事情, jvm 上面发展了很多年才有的现在强大的内存,并发模型,各种优秀的并行库和组件,这些方面 nodejs 还差的很远。。。
    haozhang
        26
    haozhang  
       2016-06-30 10:57:03 +08:00 via iPhone
    @2225377fjs 你就扯吧...还多进程...IOCP 和 epoll 被你吃了?
    2225377fjs
        27
    2225377fjs  
       2016-06-30 11:07:11 +08:00
    @haozhang 你确定我在扯? epoll 或者 kqueue 或者 iocp 是 ioloop 的实现基础,他们跟多进程多线程是同一个维度的东西。。?知道几个东西的名字就能上来装逼了?成本这么低。?不要上来就喷,把这些基础知识搞清楚了再说吧。。。
    你清楚 libevent , libev , libuv , nginx , netty , gevent 这些东西的 io 模型或者说并发模型?如果你懂的话,你可以喷。。。。如果你狗屁不通,上来就喷,那你跟 sb 喷子有啥区别。。?不过看你这个帖子的回复,我觉得你不懂,如果你懂的话,你是不会有这么弱智的回复的。
    haozhang
        28
    haozhang  
       2016-06-30 11:37:50 +08:00 via iPhone
    @2225377fjs 对的对的这些模型全是靠多进程的,和多线程没什么事!你说的好!
    haozhang
        29
    haozhang  
       2016-06-30 11:40:43 +08:00 via iPhone
    给跪了, Nodejs 靠多进程实现非阻塞 IO 的神论都出来了!神贴!
    2225377fjs
        30
    2225377fjs  
       2016-06-30 12:03:33 +08:00
    @haozhang 我说过 nodejs 靠多进程实现非阻塞 IO ?什么叫并行,什么叫并发?我说的是 nodejs 要实现并行应该是通过多进程来做,通过多进程来充分利用系统资源。
    进程线程跟 epoll 这些玩意是同一个维度的东西。。?我能说你这是恶意乱说我的意思。?或者说你根本就没看懂我的回帖的意思。

    要通过线程来实现并行计算,提高系统的计算能力,那不是 nodejs 要做的事情, nodejs 现在的框架基础也不支持这些东西,因为他根本就没有成熟的并行环境下的内存模型, java 那么多同步组件是吃白饭的,线程级别的并行也不是简简单单加个锁这么简单的事情,除了同步,还有内存可见性之类的问题。。。对于同一个数据域,在并行线程环境下,两个线程可能看到的是不同的值,这些都需要同步与内存模型来保证不会出现这种问题。 node 的框架基础根本就没有提供这些东西,因为 node 本身根本就没有想过要提供线程级别的并行,而是让系统做成多进程,这也是为什么大家说 node 不适合 CPU 运算要求特别高的任务,其实这里还少了一点东西,那就是 CPU 运算要求特别高而且业务功能模块交互比较频繁的任务不适合 node ,单纯 cpu 密集型的任务用 node 来做没问题,多开进程就行,只要各个任务之间都是独立的,交互很少。

    node 要强行实现线程并行也可以的, c++的 boost 库也有很多并行组件可用,但是这已经脱离的 nodejs 范畴。

    你这明明什么都不懂,和稀泥有意思?
    Keyes
        31
    Keyes  
       2016-06-30 22:05:58 +08:00
    @2225377fjs 你俩都不是一个 LEVEL 的,去喝茶 CODING 吧,别浪费时间了,你意思懂的人都懂
    Fontaine
        32
    Fontaine  
       2016-07-10 17:29:48 +08:00
    讨论了那么多,还是都搞清楚 node 运行在哪里,搞清楚为啥 node 叫单进程单线程,就先看看 v8
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1369 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:38 · PVG 01:38 · LAX 10:38 · JFK 13:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.