为啥要用nodejs

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥要用nodejs相关的知识,希望对你有一定的参考价值。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:FengqiAsia
链接:http://www.zhihu.com/question/19653241/answer/15993549
来源:知乎

要讲清楚这个问题,先讲讲整个Web应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈。瓶颈在于服务器能够处理的并发连接的最大数量。Node.js解决这个问题的方法是:更改连接到服务器的方式。每个连接发射一个在Node.js引擎的进程中运行的事件,而不是为每个连接生成一个新的OS线程(并为其分配一些配套内存)。Node.js不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用。Node.js还宣称,运行它的服务器能支持数万个并发连接。

Node本身运行V8 javascript。V8 JavaScript引擎是Google用于其Chrome浏览器的底层JavaScript引擎。Google使用V8创建了一个用C++编写的超快解释器,该解释器拥有另一个独特特征:您可以下载该引擎并将其嵌入任何应用程序。V8 JavaScript引擎并不仅限于在一个浏览器中运行。因此,Node.js实际上会使用Google编写的V8 JavaScript引擎,并将其重建为可在服务器上使用。

Node.js优点:
1、采用事件驱动、异步编程,为网络服务而设计。其实Javascript的匿名函数和闭包特性非常适合事件驱动、异步编程。而且JavaScript也简单易学,很多前端设计人员可以很快上手做后端设计。
2、Node.js非阻塞模式的IO处理给Node.js带来在相对低系统资源耗用下的高性能与出众的负载能力,非常适合用作依赖其它IO资源的中间层服务。3、Node.js轻量高效,可以认为是数据密集型分布式部署环境下的实时应用系统的完美解决方案。Node非常适合如下情况:在响应客户端之前,您预计可能有很高的流量,但所需的服务器端逻辑和处理不一定很多。

Node.js缺点:
1、可靠性低
2、单进程,单线程,只支持单核CPU,不能充分的利用多核CPU服务器。一旦这个进程崩掉,那么整个web服务就崩掉了。

不过以上缺点可以可以通过代码的健壮性来弥补。目前Node.js的网络服务器有以下几种支持多进程的方式:

#1 开启多个进程,每个进程绑定不同的端口,用反向代理服务器如 nginx 做负载均衡,好处是我们可以借助强大的 Nginx 做一些过滤检查之类的操作,同时能够实现比较好的均衡策略,但坏处也是显而易见——我们引入了一个间接层。
#2 多进程绑定在同一个端口侦听。在Node.js中,提供了进程间发送“文件句柄” 的功能,这个功能实在是太有用了(貌似是yahoo 的工程师提交的一个patch) ,不明真相的群众可以看这里: Unix socket magic
#3 一个进程负责监听、接收连接,然后把接收到的连接平均发送到子进程中去处理。

在Node.js v0.5.10+ 中,内置了cluster 库,官方宣称直接支持多进程运行方式。Node.js 官方为了让API 接口傻瓜化,用了一些比较tricky的方法,代码也比较绕。这种多进程的方式,不可避免的要牵涉到进程通信、进程管理之类的东西。
此外,有两个Node.js的module:multi-node 和 cluster ,采用的策略和以上介绍的类似,但使用这些module往往有一些缺点:
#1 更新不及时
#2 复杂庞大,往往绑定了很多其他的功能,用户往往被绑架
#3 遇到问题难以解决

Node表现出众的典型示例包括:

1、RESTful API
提供RESTful API的Web服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合Node的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。

2、Twitter队列
想像一下像Twitter这样的公司,它必须接收tweets并将其写入数据库。实际上,每秒几乎有数千条tweet达到,数据库不可能及时处理高峰时段所需的写入数量。Node成为这个问题的解决方案的重要一环。如您所见,Node能处理数万条入站tweet。它能快速而又轻松地将它们写入一个内存排队机制(例如memcached),另一个单独进程可以从那里将它们写入数据库。Node在这里的角色是迅速收集tweet,并将这个信息传递给另一个负责写入的进程。想象一下另一种设计(常规php服务器会自己尝试处理对数据库本身的写入):每个tweet都会在写入数据库时导致一个短暂的延迟,因为数据库调用正在阻塞通道。由于数据库延迟,一台这样设计的机器每秒可能只能处理2000条入站tweet。每秒处理100万条tweet则需要500个服务器。相反,Node能处理每个连接而不会阻塞通道,从而能够捕获尽可能多的tweets。一个能处理50000条tweet的Node机器仅需20台服务器即可。

3、电子游戏统计数据
如果您在线玩过《使命召唤》这款游戏,当您查看游戏统计数据时,就会立即意识到一个问题:要生成那种级别的统计数据,必须跟踪海量信息。这样,如果有数百万玩家同时在线玩游戏,而且他们处于游戏中的不同位置,那么很快就会生成海量信息。Node是这种场景的一种很好的解决方案,因为它能采集游戏生成的数据,对数据进行最少的合并,然后对数据进行排队,以便将它们写入数据库。使用整个服务器来跟踪玩家在游戏中发射了多少子弹看起来很愚蠢,如果您使用Apache这样的服务器,可能会有一些有用的限制;但相反,如果您专门使用一个服务器来跟踪一个游戏的所有统计数据,就像使用运行Node的服务器所做的那样,那看起来似乎是一种明智之举。

总的来说,Node.js的应用场景

1) 适合

JSON APIs——构建一个Rest/JSON API服务,Node.js可以充分发挥其非阻塞IO模型以及JavaScript对JSON的功能支持(如JSON.stringfy函数)
单页面、多Ajax请求应用——如Gmail,前端有大量的异步请求,需要服务后端有极高的响应速度
基于Node.js开发Unix命令行工具——Node.js可以大量生产子进程,并以流的方式输出,这使得它非常适合做Unix命令行工具
流式数据——传统的Web应用,通常会将HTTP请求和响应看成是原子事件。而Node.js会充分利用流式数据这个特点,构建非常酷的应用。如实时文件上传系统transloadit
准实时应用系统——如聊天系统、微博系统,但Javascript是有垃圾回收机制的,这就意味着,系统的响应时间是不平滑的(GC垃圾回收会导致系统这一时刻停止工作)。如果想要构建硬实时应用系统,Erlang是个不错的选择

2) 不适合

CPU使用率较重、IO使用率较轻的应用——如视频编码、人工智能等,Node.js的优势无法发挥
简单Web应用——此类应用的特点是,流量低、物理架构简单,Node.js无法提供像Ruby的Rails或者Python的Django这样强大的框架
NoSQL + Node.js——如果仅仅是为了追求时髦,且自己对这两门技术还未深入理解的情况下,不要冒险将业务系统搭建在这两个漂亮的名词上,建议使用mysql之类的传统数据库

如果系统可以匹配Node.js的适用场景,那么是时候采取具体的措施来说服老板了。

说服自己老板采用Node.js的方式

构建一个简单的原型——花一周时间构建系统某一部分的原型是非常值得的,同时也很容易和老板在某一点达成一致,等到系统真的在某一部分应用了Node.js,就是打开局面的时候
寻找开发者——首先JavaScript语言的普及度很高,一般公司都不乏Web前端工程师,而此类工程师的学习门槛也非常低。这就意味着Node.js很容易招人,或者公司就隐藏了一些高手
强大的社区支持——Node.js社区非常活跃,吸引很多优秀的工程师,这就意味着公司可以很容易从社区得到免费或者付费的支持
系统性能考虑——JavaScript引擎Google V8,加之原生异步IO模型,使得Node.js在性能的表现非常出色,处理数以千计的并发请求非常轻松
专业公司的支持——使用开源技术的最大问题是,原作者不承诺对其产品进行技术支持或者质量保证。现在Node.js已经得到Joyent公司的赞助,这就保证了未来Node.js的发展是可持续性的
参考技术A 北漂的心酸,公众号,最新node.js从入门到精通及服务器搭建课程

为啥要用多列作为主键(复合主键)

【中文标题】为啥要用多列作为主键(复合主键)【英文标题】:Why use multiple columns as primary keys (composite primary key)为什么要用多列作为主键(复合主键) 【发布时间】:2011-02-07 05:50:14 【问题描述】:

这个例子取自from w3schools。

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255),
    CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)

我的理解是两列(P_IdLastName)一起代表表Persons 的主键。这是正确的吗?

为什么有人要使用多列而不是单列作为主键? 在给定表中可以将多少列一起用作主键?

【问题讨论】:

...现在还有一个answer for the 2'nd question @Martijn Peters。为什么答案被删除了? 【参考方案1】:

你的理解是正确的。

在很多情况下你会这样做。一个例子是像OrderHeaderOrderDetail 这样的关系。 OrderHeader 中的 PK 可能是 OrderNumberOrderDetail 中的 PK 可能是 OrderNumberLineNumber。如果是这两者中的任何一个,它就不会是唯一的,但两者的组合保证是唯一的。

替代方法是使用生成的(非智能)主键,例如在本例中为 OrderDetailId。但是你不会总是那么容易地看到这种关系。有些人喜欢一种方式;有些人更喜欢另一种方式。

【讨论】:

如果我使用 branch_id 并使用两个数据库之间的复制,这是否有用,将解决 ids 的重复?!! 请注意,在许多使用生成的主键的情况下,您通常仍需要复合值上的唯一键。 请详细说明“有些人喜欢一种方式;有些人喜欢另一种方式”。 请详细说明?不知道该说些什么。我认识一些人喜欢将多个连接字段作为键,因为更容易直观地理解他们正在查看的内容。我知道其他人更喜欢只为每一行分配一个唯一的键,因为它更容易和更快地输入。你问的是这个吗? 该消息是给@Username的。我忘记指导了。【参考方案2】:

复合主键的另一个例子是关联表的使用。假设您有一个包含一组人员的人员表和一个包含一组组的组表。现在你想在人和组上创建多对多关系。这意味着每个人都可以属于许多组。以下是使用复合主键的表结构。

Create Table Person(
PersonID int Not Null,
FirstName varchar(50),
LastName varchar(50),
Constraint PK_Person PRIMARY KEY (PersonID))

Create Table Group (
GroupId int Not Null,
GroupName varchar(50),
Constraint PK_Group PRIMARY KEY (GroupId))

Create Table GroupMember (
GroupId int Not Null,
PersonId int Not Null,
CONSTRAINT FK_GroupMember_Group FOREIGN KEY (GroupId) References Group(GroupId),
CONSTRAINT FK_GroupMember_Person FOREIGN KEY (PersonId) References Person(PersonId),
CONSTRAINT PK_GroupMember PRIMARY KEY (GroupId, PersonID))

【讨论】:

很好的解释:我认为 m-to-n 关系(在规范化的方式中)需要属性是关键。 加点福利说明会更好【参考方案3】:

W3Schools 示例并没有说明何时应该使用复合主键,只是给出了使用与其他键相同的示例表的示例语法。

他们选择的示例可能会通过组合无意义的键 (P_Id) 和自然键 (LastName) 来误导您。这种奇怪的主键选择表明以下行根据架构是有效的,并且是唯一标识学生所必需的。直觉上这是没有意义的。

1234     Jobs
1234     Gates

进一步阅读:The great primary-key debate 或只是谷歌meaningless primary keys 甚至细读这个SO question

FWIW - 我的 2 美分是避免多列主键,并使用单个生成的 id 字段(代理键)作为主键,并在必要时添加额外(唯一)约束。

【讨论】:

1) “伟大的主键辩论”链接特别愚蠢,信息是自私的和虚假的。 2)无法避免使行唯一的列上的索引。带有索引的“代理”ID 始终是附加列和附加索引。相当愚蠢,因为它是多余的。而且更慢。 “伟大的主键辩论”并不愚蠢。对于不是 sql 开发人员或 sql DBA 并且不会将所有时间都花在 sql 上的开发人员来说,这是一个非常有效的问题。即使在纯 sql 中,我也宁愿在加入时将无意义的自动生成的键作为主键,而不是记住传递 n 位数据作为自然键。欢迎您提出自己的观点,但我们希望您不要如此轻视。【参考方案4】:

只要您想确保多个属性组合的唯一性,您就可以使用复合键(具有多个属性的键)。单个属性键不会达到同样的效果。

【讨论】:

为了保证key的唯一性,你可以依靠两个属性的组合来形成一个逻辑上不能重复的key,比如大数据集中的Person和毕业日期。【参考方案5】:

是的,它们都构成了主键。特别是在没有surrogate key 的表中,可能需要指定多个属性作为每条记录的唯一标识符(不好的示例:同时具有名字和姓氏的表可能需要将它们组合起来是独一无二的)。

【讨论】:

【参考方案6】:

一个键中的多个列通常比代理键的性能更差。我更喜欢有一个代理键,然后是一个多列键上的唯一索引。这样,您可以获得更好的性能并保持所需的唯一性。更好的是,当该键中的一个值发生更改时,您也不必更新 215 个子表中的一百万个子条目。

【讨论】:

1) 性能。不在 SQL 平台中(可能在假装的“sql”和免费软件中)。 2) 偏好无关紧要。为了完整性,表格需要什么是相关的。 3) 带有索引的“代理”ID 始终是 additional 列和 additional 索引。所以在任何平台上都会更慢。重新表现,你自相矛盾。 4) 如果您不知道如何正确更新神话中的“215 个子表中的百万个子条目”,请提出问题。 我不同意“一个键中的多个列通常比代理键的性能更差”的说法。当您考虑关系时,通常需要额外的查询来获取关系的代理键。在这一点上,这是一个完整的额外往返更慢的性能明智。【参考方案7】:

你的第二个问题

在给定的表中,有多少列可以一起用作主键?

是特定于实现的:它是在实际使用的 DBMS 中定义的。[1],[2],[3] 您必须检查您使用的数据库系统的技术规范。有些非常详细,有些则不然。在网络上搜索这些限制可能很困难,因为术语会有所不同。 复合主键这个词应该是强制性的;)

如果您找不到明确的信息,请尝试创建一个测试数据库,以确保您可以稳定(且具体)地处理限制违规(这是意料之中的)。请注意获取有关此方面的正确信息:有时会累积限制,您会看到不同数据库布局的不同结果。


[1]sql - Composite primary key limit? - Stack Overflow [2]SQL Server - Max columns per primary key [3]How many maximum number of columns can be part of Primary Key in a table in Oracle 9i and 10g?

【讨论】:

【参考方案8】:

在关系数据库中使用中间表时,在多个表上使用主键会派上用场。

我将使用我曾经制作的数据库作为示例,特别是该表中的三个表。几年前,我为网络漫画创建了一个数据库。一个表称为“comics”——列出所有漫画、它们的标题、图像文件名等。主键是“comicnum”。

第二个表是“字符”——它们的名称和简要描述。主键在“charname”上。

由于每部漫画(除了一些例外)都有多个角色,并且每个角色都出现在多部漫画中,因此在“角色”或“漫画”中放置一列来反映这一点是不切实际的。相反,我创建了一个名为“comicchars”的 third 表,它列出了哪些角色出现在哪些漫画中。由于该表本质上是连接两个表,因此它只需要两列:charname 和comicnum,并且主键在两者上。

【讨论】:

【参考方案9】:

我们创建复合主键来保证组成单个记录的列值的唯一性。这是一个约束,有助于防止插入不应重复的数据。

即:如果所有学生 ID 和出生证明号码都唯一分配给一个人。那么最好将一个人的主键设置为学生 ID 和出生证明号码的组合,因为这样可以防止您意外插入两个具有不同学生 ID 和相同出生证明的人。

【讨论】:

以上是关于为啥要用nodejs的主要内容,如果未能解决你的问题,请参考以下文章

数据库连接池为啥要用 ThreadLocal?

stm32 为啥要用freertos

为啥要用nodejs

数据库连接池为啥要用 ThreadLocal?

为啥要用Dubbo?

关于NodeJs为啥要用mongoose操作mongodb