×

Loading...

今天抽空大概看了看node.js,就这个单线程event的问题说说。

本文发表在 rolia.net 枫下论坛我没太仔细研究,所以只是粗谈,很多概念都是以前积累的,也许有记错的,还请大家海涵。

Javascript和C++并不存在谁强谁弱的问题。说到底,语言是工具,能用不同的工具干不同的事情更重要。node.js整个底层是chromeV8引擎。V8就是用C++写的。所以说JavaScript可以用event调用,而C++只能调线程,这个看法并不正确。C++几乎可以干任何事情,只是大家有没有这样去用而已。

javascript的单线程并行是误传,单线程永远是不能并行的。在V8引擎的后台其实是有线程池的。所谓的单线程只是指运行你的javascript代码的那个主线程。一旦你发出event了,里面是有其他线程来处理这些消息的。event解决的是一个阻塞的问题。

说到阻塞,阻塞很多地方都有,最常见的就是网卡,硬盘,数据库。比如用C++写一个socket程序(web服务器最底层的一些代码)
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
pid = fork(); // 这里就开始起线程了。
if (pid < 0) error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd); //这里开始干活了,干什么呢?读写网卡。阻塞问题就出在这里。
exit(0);
} else close(newsockfd);

n = write(sockfd,buffer,strlen(buffer)); n = read(sockfd,buffer,255); 这两个读写,都是阻塞的。于是一个人在那里读写,就都等着。等着网络慢慢把数据传过来,等着缓存,等着读。等死人。

那么后来呢,就有了select/poll。 select/poll的好处就是你不用等了。有一个监听者来给你轮询。看看你这个socket读完了没有啊?没有?没有继续读,不等。读完了?读完了就处理。轮询呢?有几个人在连,就问几个人。那有些人根本就是闲着,你也去问?这也慢。所以后来就有了epoll。epoll就不是轮询了,e就是event。所以说C++没有event那个是不明所以。网卡数据读到了,发一个event出来,然后就处理。那线程呢?线程就解放了。以前是有一个请求你就起一个线程来处理,现在是一个线程可以处理好多个请求,因为在等网卡的那闲工夫它可以干其他事情么。所以就有了worker线程,也就有了线程池。通过有限的worker线程,来处理更多的请求。那么这个做得最好的一位就是nginx。所以谈到web服务器,大家就拿aparche来说事。其实Aparche做得是很烂的。真正要讲速度,应该谈nginx,这位实现了我上面讲的所有技术。当年看它的源码的时候,发现它什么都支持。当然是需要配置的。配置得不好也慢。

当然,node.js还有很牛的地方就是一切皆事件,也就是把一切io都可以多线程干了。nginx作为web服务器,这是它的本职,但你写数据库那是应用的事情。它就不管了。而node。js因为它是javascript语言么,所以这个利用线程池就是随时随地都可以用。这方面的确不错。但是node.js主线程的程序复杂呢?那它就完了。因为它是一个单线程程序啊。你如果把主线程block住,node.js就死掉了。所以再好的工具也得会用才行。当然,node.js之所以快,不是因为javascript快,而是因为V8引擎快。说到底还是C++快。在此向google表达一下敬意。更多精彩文章及讨论,请光临枫下论坛 rolia.net
Sign in and Reply Report