如何决定何时使用Node.js?

时间:2011-02-21 05:20:51

标签: javascript node.js web-applications

我是这类新手,但最近我听到很多关于Node.js有多好的事情。考虑到我一般喜欢使用jQuery和JavaScript,我不禁想知道如何决定何时使用Node.js.我想到的Web应用程序类似于Bitly - 获取一些内容,将其归档。

在过去几天我一直在做的所有作业中,我获得了以下信息。 Node.js

  • 是一个命令行工具,可以作为常规Web服务器运行,让一个人运行JavaScript程序
  • 利用了很棒的V8 JavaScript engine
  • 当你需要同时做几件事时,
  • 非常好
  • 是基于事件的,所以所有精彩的Ajax - 类似的东西都可以在服务器端完成
  • 让我们在浏览器和后端之间共享代码
  • 让我们与MySQL讨论

我遇到的一些消息来源是:

考虑到Node.js几乎可以在Amazon's EC2个实例上运行,我试图了解哪些类型的问题需要Node.js,而不是任何强大的国王。例如PHPPythonRuby。我明白这实际上取决于对语言的专业知识,但我的问题更多地涉及一般类别:何时使用特定框架以及它特别适合哪种类型的问题?

17 个答案:

答案 0 :(得分:1358)

你总结了Node.js的精彩内容。我的感觉是Node.js特别适合于您希望保持从浏览器到服务器的持久连接的应用程序。使用称为"long-polling"的技术,您可以编写一个实时向用户发送更新的应用程序。对许多网络巨头进行长时间轮询,例如Ruby on RailsDjango,会在服务器上产生巨大负荷,因为每个活动客户端都会占用一个服务器进程。这种情况相当于tarpit次攻击。当您使用Node.js之类的东西时,服务器不需要为每个打开的连接维护单独的线程。

这意味着您可以在Node.js中创建browser-based chat application,几乎不需要任何系统资源来为很多客户端提供服务。任何时候你想做这种长轮询,Node.js是一个很好的选择。

值得一提的是,Ruby和Python都有工具来完成这类事情(分别为eventmachinetwisted),但是Node.js做得非常好,从头开始。 JavaScript非常适合基于回调的并发模型,并且在这方面表现优异。此外,能够使用本机的JSON序列化和反序列化客户端和服务器是非常好的。

我期待在这里阅读其他答案,这是一个很棒的问题。

值得指出的是,Node.js也适用于在客户端/服务器间隙中重复使用大量代码的情况。 Meteor framework使这非常简单,很多人都认为这可能是Web开发的未来。我可以从经验中说,在Meteor中编写代码非常有趣,其中很大一部分是花更少的时间考虑如何重构数据,因此浏览器中运行的代码很容易操纵它并将其传回去。

这是一篇关于金字塔和长轮询的文章,结果很容易在gevent的帮助下设置:TicTacToe and Long Polling with Pyramid

答案 1 :(得分:409)

我相信Node.js最适合实时应用:在线游戏,协作工具,聊天室,或其他用户(或机器人?或传感器?)对应用程序的作用需要被其他人看到的任何内容用户立即,没有页面刷新。

我还应该提一下,Socket.IO与Node.js结合使用会比长轮询更进一步减少实时延迟。 Socket.IO将在最糟糕的情况下回归长轮询,而是使用网络套接字,甚至是Flash,如果它们可用的话。

但我还应该提一下,使用Node.js可以更好地解决代码因线程而阻塞的任何情况。或者您需要应用程序进行事件驱动的任何情况。

此外,Ryan Dahl在一次谈话中说,我曾经参加过Node.js基准测试,与Ng​​inx的常规旧HTTP请求密切相关。因此,如果我们使用Node.js构建,我们可以非常有效地服务我们的常规资源,当我们需要事件驱动的东西时,它就可以处理它了。

另外,它一直都是JavaScript。 Lingua Franca整个堆栈。

答案 2 :(得分:209)

使用NodeJS的原因:

  • 它运行Javascript,因此您可以在服务器和客户端上使用相同语言,甚至可以在它们之间共享一些代码(例如,用于表单验证,或在两端呈现视图)。 )

  • 与传统的多线程single-threaded或ROR框架相比,fast事件驱动系统即使在处理大量请求时也是Java,而且也很简单。

  • 不断增长的 packages可通过NPM 访问,包括客户端和服务器端库/模块,以及用于Web开发的命令行工具。其中大多数都方便地托管在github上,有时您可以报告问题并在几小时内找到它!将所有内容集中在一个屋檐下,标准化的问题报告和简单的分叉是很好的。

  • 它已成为运行与Javascript相关的工具以及其他与网络相关的工具的事实标准环境,包括任务运行器,缩放器,美化器,连接器,预处理器,捆绑器和分析处理器。

  • 它似乎非常适合原型设计,敏捷开发和快速产品迭代

的原因使用NodeJS:

  • 它运行Javascript,没有编译时类型检查。对于大型,复杂的安全关键系统或项目(包括不同组织之间的协作),鼓励合同接口并提供静态类型检查的语言可能从长远来看,可以节省一些调试时间(以及爆炸)。 (虽然JVM卡在null,但请将Haskell用于核反应堆。)

  • 除此之外,NPM中的许多软件包都有点原始,并且仍处于快速发展阶段。旧框架的一些库经历了十年的测试和错误修正,现在非常稳定Npmjs.org has no mechanism to rate packages,导致包裹大量增加或多或少相同,其中很大一部分不再维持。

  • 嵌套回调地狱。 (当然这里有20 different solutions ...)

  • 不断增长的软件包可以使一个NodeJS项目与下一个项目显示完全不同。由于可用选项数量巨大(例如Express / Sails.js / Meteor / Derby),实施方式存在很大差异。这有时会使新开发人员更难进入Node项目。与加入现有项目的 Rails 开发人员形成对比:他应该能够很快熟悉应用程序,因为鼓励所有Rails应用程序使用类似结构

  • 处理文件可能会有点痛苦。其他语言中的一些小事,比如从文本文件中读取一行,weird enough to do with Node.js就有一个StackOverflow问题就是80+ upvotes。有no simple way to read one record at a time from a CSV file。等

我喜欢NodeJS,它既快又狂野又有趣,但我担心它对可证明的正确性几乎没有兴趣。让我们希望我们最终可以融合两全其美。我很想知道将来会取代Node ...:)

答案 3 :(得分:207)

简而言之:

Node.js非常适合具有大量并发连接的应用程序,每个请求只需要很少的CPU周期,因为在执行函数期间会阻止事件循环(包含所有其他客户端)。

有关Node.js中事件循环的好文章是Mixu's tech blog: Understanding the node.js event loop

答案 4 :(得分:127)

我有一个真实世界的例子,我使用过Node.js.我工作的公司有一个客户希望拥有一个简单的静态HTML网站。本网站用于使用PayPal销售一件商品,客户也希望有一个显示销售商品数量的柜台。客户预计会有大量访问者访问本网站。我决定使用Node.js和Express.js框架来制作计数器。

Node.js应用程序很简单。从Redis数据库中获取已售商品金额,在商品售出时增加计数器,并通过API向用户提供计数器值。

在这种情况下我选择使用Node.js的一些原因

  1. 非常轻巧,快速。本网站在三周内访问量超过20万次,服务器资源最少。
  2. 计数器真的很容易实时。
  3. Node.js很容易配置。
  4. 免费提供许多模块。例如,我找到了PayPal的Node.js模块。
  5. 在这种情况下,Node.js是一个很棒的选择。

答案 5 :(得分:105)

使用Node ...

启动下一个项目的最重要原因
  • 所有最酷的家伙都参与其中......所以必须才能充满乐趣。
  • 你可以在冷却器上进行聚会,并有很多Node冒险来吹嘘。
  • 在云托管成本方面,你只是一分钱。
  • 用Rails做过那件事
  • 您讨厌IIS部署
  • 你的旧IT工作变得相当沉闷,你希望你处于一个闪亮的新起点。

期待什么......

  • 使用Express,您将感到安全无虞,而不需要您从未需要的所有服务器臃肿软件。
  • 像火箭一样运行并且可以很好地扩展。
  • 你梦见它。你安装了它。节点包repo npmjs.org是世界上最大的开源库生态系统。
  • 你的大脑会在嵌套回调的土地上翘曲......
  • ...直到您学会保留Promises
  • SequelizePassport是您的新API好友。
  • 调试大部分异步代码将获得嗯...... 有趣
  • 所有节点制作者掌握Typescript的时间。

谁使用它?

  • PayPal,Netflix,Walmart,LinkedIn,Groupon,Uber,GoDaddy,Dow Jones
  • 这就是他们switched to Node的原因。

答案 6 :(得分:60)

没有像银弹一样的东西。一切都带来了与之相关的一些成本。就像你吃油腻的食物,你会损害你的健康,健康的食物不会像油性食物一样。无论他们是否想要健康或香料,都是个人选择。 Node.js考虑在特定场景中使用的方式相同。如果您的应用不适合该方案,则不应将其视为您的应用开发。我只是想到了同样的想法:

何时使用Node.JS

  1. 如果您的服务器端代码需要很少的CPU周期。在其他世界中,您正在执行非阻塞操作,并且没有繁重的算法/作业,这会消耗大量的CPU周期。
  2. 如果您来自Javascript,并且在编写单线程代码时非常舒服,就像客户端JS一样。
  3. 何时不使用Node.JS

    1. 您的服务器请求取决于耗费大量CPU的算法/作业。
    2. Node.JS的可扩展性考虑

      1. Node.JS本身不利用底层系统的所有核心,默认情况下它是单线程的,你必须自己编写逻辑来利用多核处理器并使其成为多线程。
      2. Node.JS替代方案

        还有其他选项可用来代替Node.JS,但是Vert.x似乎非常有前途,并且有许多其他功能,如polygot和更好的可扩展性考虑。

答案 7 :(得分:41)

我认为没有人提到过关于Node.js的另一件好事是令人惊叹的社区,包管理系统(npm)以及存在的模块数量,只需包括它们在你的package.json文件中。

答案 8 :(得分:37)

我的文章:nodejs非常适合制作分析,聊天应用,api,广告服务器等实时系统。 天啊,我在2小时内使用nodejs和socket.io创建了我的第一个聊天应用程序 一周!

修改

自从我开始使用nodejs已经有好几年了,我已经用它来制作许多不同的东西,包括静态文件服务器,简单的分析,聊天应用程序等等。 这是我对何时使用nodejs的看法

何时使用

制作强调并发性和速度的系统时。

  • 仅支持聊天应用,irc应用等服务器
  • 社交网络,强调地理位置,视频流,音频流等实时资源
  • 像分析网络应用程序一样快速处理小块数据。
  • 仅暴露REST api。

何时不使用

它是一个非常通用的网络服务器,所以你可以在任何你想要的地方使用它,但可能不是这些地方。

  • 简单的博客和静态网站。
  • 就像静态文件服务器一样。

请记住,我只是在挑剔。对于静态文件服务器,apache更好,主要是因为它广泛可用。 nodejs社区多年来变得越来越大,越来越成熟,如果你有自己选择的托管,可以安全地说nodejs可以在任何地方使用。

答案 9 :(得分:30)

可以在

的地方使用
  • 高度事件驱动的应用程序&严重受I / O约束
  • 处理与其他系统的大量连接的应用程序
  • 实时应用程序(Node.js是从头开始设计的,实时且易于使用 使用。)
  • 将大量信息流与其他来源混合的应用程序
  • 高流量,可扩展的应用程序
  • 必须与平台API&数据库,无需做大量数据 分析
  • 构建联网应用程序
  • 需要经常与后端交谈的应用程序

在移动方面,黄金时段的公司依靠Node.js来提供移动解决方案。 查看原因?

LinkedIn是一位杰出的用户。他们的整个移动堆栈都是基于Node.js构建的。他们从每个物理机器上运行15个服务器,15个实例,到4个实例 - 可以处理双倍的流量!

eBay启动了ql.io,这是一种用于HTTP API的Web查询语言,它使用Node.js作为运行时堆栈。他们能够调整常规开发人员质量的Ubuntu工作站,以处理每个node.js进程超过120,000个活动连接,每个连接消耗约2kB内存!

Walmart重新设计了其移动应用,以使用Node.js并将其JavaScript处理推送到服务器。

阅读详情:http://www.pixelatingbits.com/a-closer-look-at-mobile-app-development-with-node-js/

答案 10 :(得分:20)

Node best for concurrent request handling -

所以,让我们从一个故事开始吧。从过去的两年开始,我正致力于JavaScript和开发Web前端,我很享受。后端人员提供了一些用Java编写的API,python(我们不关心),我们只是编写一个AJAX调用,获取我们的数据并猜测是什么!我们完了。但实际上并不是那么容易,如果我们得到的数据不正确或者存在服务器错误,那么我们就会陷入困境,我们必须通过邮件或聊天联系我们的后端人员(有时也会在whatsApp上:)。)并不酷。如果我们用JavaScript编写API并从前端调用这些API,该怎么办?是的,这很酷,因为如果我们在API中遇到任何问题,我们可以调查它。你猜怎么着 !你现在可以这样做,怎么样? - 节点就在你身边。

Ok同意您可以用JavaScript编写API,但如果我对上述问题感到满意怎么办。您是否有任何其他理由将节点用于rest API?

所以这就是神奇的开始。是的我还有其他理由将节点用于我们的API。

让我们回到我们传统的rest API系统,该系统基于阻塞操作或线程。假设发生了两个并发请求(r1和r2),每个请求都需要数据库操作。所以在传统系统中会发生什么:

<强> 1。等待方式:我们的服务器开始提供r1请求并等待查询响应。完成r1后,服务器开始提供r2并以相同方式执行。所以等待并不是一个好主意,因为我们没有那么多时间。

<强> 2。线程方式:我们的服务器将为请求r1r2创建两个线程,并在查询数据库之后快速实现其目的。但它很耗费内存,因为您可以看到我们已经开始两个线程也问题增加当两个请求都查询相同的数据然后你必须处理死锁类问题。所以它比等待方式更好,但仍有问题。

现在,节点将如何执行此操作:

第3。节点:当同一个并发请求进入节点时,它将使用其回调注册事件并向前移动它不会等待特定请求的查询响应。所以当r1请求到来时节点的事件循环(是的,节点中有一个事件循环用于此目的。)使用其回调函数注册事件并向前移动以提供r2请求,并类似地使用其回调注册其事件。每当任何查询完成时,它会触发相应的事件并执行其回调以完成而不会被中断。

所以没有等待,没有线程,没有内存消耗 - 是的,这是服务其余API的节点。

答案 11 :(得分:16)

我的另一个原因为新项目选择Node.js是:

能够进行基于纯云的开发

我已经使用了Cloud9 IDE一段时间了,现在我无法想象没有它,它涵盖了所有的开发生命周期。您所需要的只是一个浏览器,您可以随时随地在任何设备上进行编码。您无需在一台计算机中签入代码(如在家中),然后在另一台计算机(例如在工作场所)结账。

当然,基于云的IDE可能适用于其他语言或平台(Cloud 9 IDE也增加了对其他语言的支持),但使用Cloud 9进行Node.js开发对我来说真的是一次很棒的体验。

答案 12 :(得分:15)

节点提供的另一个功能是能够使用节点的子进程(childProcess.fork(),每个需要10mb内存,根据文档)创建多个v8节点的节点,从而不影响主进程运行服务器。因此,卸载需要大量服务器负载的后台作业会成为孩子的游戏,我们可以在需要时轻松杀死它们。

我一直在使用节点,在我们构建的大多数应用程序中,同时需要服务器连接,因此网络流量很大。像Express.js这样的框架和新的Koajs(删除了回调地狱)使节点上的工作变得更加容易。

答案 13 :(得分:15)

穿上石棉长枪......

昨天我的Packt出版物标题Reactive Programming with JavaScript。它不是一个以Node.js为中心的标题;前面的章节旨在涵盖理论,后来代码密集的章节涵盖了实践。因为我并不认为没有给读者一个网络服务器是合适的,所以Node.js似乎 到目前为止 是明显的选择。该案件甚至在开业前已经关闭。

我可以非常了解我对Node.js的体验。相反,我诚实地谈到了我遇到的好点和坏点。

让我在这里提供一些与之相关的引用:

  

警告:Node.js及其生态系统 - 足够热,可能会严重烧伤你!

     

当我是数学老师的助手时,我被告知的一个非显而易见的建议就是不要告诉学生一些事情是“容易的”。回想起来,原因有点明显:如果你告诉别人什么是容易的话一个没有看到解决方案的人最终可能感觉到(甚至更多)愚蠢,因为他们不仅没有得到如何解决问题,而且他们太愚蠢无法理解的问题是一个简单的问题!

     

有些问题并不只是让来自Python / Django的人感到烦恼,如果你改变任何东西,它会立即重新加载源代码。对于Node.js,默认行为是,如果进行一次更改,旧版本将继续处于活动状态,直到时间结束或直到您手动停止并重新启动服务器。这种不恰当的行为不仅会惹恼Pythonistas;它还会激怒提供各种解决方法的本机Node.js用户。在撰写本文时,StackOverflow问题“在Node.js中自动重新加载文件”有200多个upvotes和19个答案;编辑将用户定向到保姆脚本,节点主管,主页位于http://tinyurl.com/reactjs-node-supervisor。这个问题为新用户提供了很大的机会感到愚蠢,因为他们认为他们已经解决了问题,但旧的,错误的行为完全没有改变。并且很容易忘记反弹服务器;我已多次这样做了。我想提供的信息是:“不,你不是傻瓜,因为Node.js的这种行为让你感到厌倦;只是Node.js的设计者没有理由在这里提供适当的行为。尝试应对它,也许从节点主管或其他解决方案中获得一些帮助,但请不要忘记你是愚蠢的。你不是那个有问题的人;问题出在Node.js的默认行为中。“

     

经过一番辩论之后,这部分被遗留下来,正是因为我不想给人一种“这很容易”的印象。我在做事情的时候反复剪了手,我不想要解决困难并让你相信让Node.js和它的生态系统运行良好是一件简单的事情,如果它对你来说也不是直截了当的,你就不知道你在做什么。如果你没有使用Node.js遇到令人讨厌的困难,那太好了。如果你这样做,我希望你不要离开感觉,“我很愚蠢 - 我一定有问题。”如果你遇到与Node.js有关的令人讨厌的惊喜,你就不傻了。不是你!它是Node.js及其生态系统!

在最后几章和结论中逐渐提升后,我并不真正想要的附录说明了我在生态系统中能够找到的内容,并为愚蠢的文字主义提供了一种解决方法:

  

另一个看起来非常合适且可能可以兑换的数据库是HTML5键值存储的服务器端实现。这种方法具有API的主要优势,大多数优秀的前端开发人员都能很好地理解。就此而言,它也是一个API,大多数不那么优秀的前端开发人员都能很好地理解。但是使用node-localstorage包,虽然不提供字典语法访问(您希望使用localStorage.setItem(key,value)或localStorage.getItem(key),而不是localStorage [key]),但实现了完整的localStorage语义,包括默认的5MB quota- 为什么?服务器端JavaScript开发人员是否需要保护他们自己?

     

对于客户端数据库功能,每个网站5MB的配额确实是一个慷慨而有用的空间,让开发人员可以使用它。你可以设置一个低得多的配额,并且仍然为开发人员提供了一个不可估量的改进,而不是一瘸一拐地进行cookie管理。 5MB的限制并不能很快适应大数据客户端处理,但是资源丰富的开发人员可以用来做很多事情,这是一个非常慷慨的限制。但另一方面,5MB并不是最近购买的大多数磁盘的一个特别大的部分,这意味着如果你和一个网站不同意什么是合理使用磁盘空间,或者某些网站只是很糟糕,它并不真正花费你很多,除非你的硬盘已经太满,否则你没有淹没硬盘的危险。如果余额少一点或多一点,我们可能会更好,但总体而言,它是解决客户端背景的内在紧张的一个不错的解决方案。

     

但是,可能会轻轻地指出,当您是服务器的代码编写者时,您不需要任何额外的保护来使您的数据库超过5MB的容量。大多数开发人员既不需要也不希望工具充当保姆,并保护他们不要存储超过5MB的服务器端数据。而在客户端的5MB配额是一个黄金平衡行为在Node.js服务器上相当愚蠢。 (并且,对于本附录中涵盖的多个用户的数据库,可能会略微痛苦地指出,除非您为每个用户帐户在磁盘上创建单独的数据库,否则每个用户帐户不会为5MB;这是5MB之间共享所有用户帐户在一起。如果你病毒式传播,可能会感到非常痛苦。文档说明配额是可自定义的,但是一周前给开发人员的一封电子邮件询问如何更改配额是没有答案的,如StackOverflow问题是一样的问题。我能找到的唯一答案是在Github CoffeeScript源代码中,它被列为构造函数的可选第二个整数参数。所以这很容易,您可以指定一个等于磁盘或分区大小的配额。但是除了移植一个没有意义的功能之外,该工具的作者完全没有遵循一个非常标准的解释0的约定,因为变量或函数的含义是“无限制”,其中整数是指定某些资源使用的最大限制。最好的办法就是指定配额为无限:

if (typeof localStorage === 'undefined' || localStorage === null)
  {      
  var LocalStorage = require('node-localstorage').LocalStorage;
  localStorage = new LocalStorage(__dirname + '/localStorage',
    Infinity);
  }

按顺序交换两条评论:

  

人们不断地使用JavaScript作为一个整体来自己的脚,并且JavaScript的一部分被制作成可敬的语言是Douglas Crockford本质上说,“JavaScript作为一种语言有一些非常好的部分和一些非常糟糕的部分。这是好的部分。只要忘记其他任何东西都在那里。“也许热门的Node.js生态系统会增长它的拥有”Douglas Crockford,“谁会说,”Node.js生态系统是编码狂野西部,但那里是一些真正的宝石可以找到。这是一个路线图。以下是几乎不惜任何代价避免的区域。以下是可以在任何语言或环境中找到最丰富的付费区域。“

     

也许其他人可以将这些话作为挑战,并遵循Crockford的主导并为Node.js及其生态系统写下“好的部分”和/或“更好的部分”。我买了一份!

     

考虑到所有项目的热情程度和工作时间,可能需要在一年,或两年,或三年内,对本文撰写时对未成熟生态系统的任何评论进行尖锐的评论。在五年内说“2015 Node.js生态系统有几个雷区”真的很有意义。 2020 Node.js生态系统有多个天堂。“

答案 14 :(得分:9)

如果您的应用程序主要使用web apis或其他io频道,提供或采用用户界面,node.js可能是一个公平的选择,特别是如果你想要挤出最大的可扩展性,或者,如果你的主要生活中的语言是javascript(或各种javascript转换器)。如果你构建微服务,node.js也没关系。 Node.js也适用于任何小型或简单的项目。

它的主要卖点是它允许前锋负责后端的东西,而不是典型的鸿沟。另一个合理的卖点是,如果您的员工以javascript为导向开始。

但是,除了某一点之外,如果没有可怕的黑客攻击来强制模块化,可读性和流量控制,则无法扩展代码。有些人喜欢那些黑客,特别是来自事件驱动的javascript背景,他们似乎熟悉或可原谅。

特别是,当您的应用程序需要执行同步流程时,您会开始放弃半生不熟的解决方案,这会在开发过程中大大降低您的速度。如果您的应用程序中有计算密集型部件,请谨慎选择(仅限)node.js.与我最初使用node.js或写这篇文章相比,也许http://koajs.com/或其他新奇事物可以缓解那些最初棘手的方面。

答案 15 :(得分:-2)

我可以分享几点,以及为什么要使用节点js。

  1. 对于聊天,协作编辑等实时应用程序,我们更好地使用nodejs,因为它是事件库,从服务器向客户端发送火灾事件和数据。
  2. 简单易懂,因为它是大多数人都有想法的javascript基础。
  3. 大多数当前的Web应用程序都转向角度js&amp; backbone,使用节点很容易与客户端代码交互,因为它们都将使用json数据。
  4. 可用的插件很多。
  5. 缺点: -

    1. Node将支持大多数数据库,但最好的是mongodb,它不支持复杂的连接和其他数据库。
    2. 编译错误......如果任何错误,应用程序将停止工作,我们需要再次手动或使用任何自动化工具启动它,开发人员应该处理其他每个例外。
    3. 结论: - Nodejs最适合用于简单和实时的应用程序..如果你有非常大的业务逻辑和复杂的功能,那么最好不要使用nodejs。 如果您想构建一个应用程序以及聊天和任何协作功能..节点可以在特定部分中使用,并且应该使用您的便利技术。

答案 16 :(得分:-3)

  1. 节点非常适合快速原型,但我从不再用它来复制任何东西。 我花了20年时间与编译器建立关系,我肯定想念它。

  2. Node对于维护您暂时无法访问的代码特别痛苦。类型信息和编译时错误检测是好事。为什么抛出这一切?为了什么?而且,当东西向南移动时,堆栈痕迹往往完全无用。

相关问题