归来的技术栈——无状态的服务端

归来的技术栈——无状态的服务端

大家好,又见面了,我是全栈君。

本系列文章都是以方便开发和维护为出发点,在可能的时候,尽量兼顾性能方面的需求

本文是 归来的技术栈 的第三篇,必要时请阅读链接中的内容了解背景。

如果拿 Node.js 和 PHP 比较,我向来是喜欢 Node 多一点。但有一点是 PHP 天然具备, 而 Node 需要付出一些努力才能实现的。

默认情况下,PHP 针对每个请求会使用独立的进程来处理,完成后即销毁。虽然从性能上来说,每次执行都要重复加载文件和数据会带来负面影响,但在另一些方面,却有着先天优势。

比如某个请求发生了错误,不会对另一个请求造成影响;内存泄漏的负面效果无法累积起来影响系统的长期稳定运行;在一定程度上只要堆服务器就可以横向扩展来提高并发能力;不需要针对服务器启停编写额外的代码来初始化和扫尾;服务器意外关闭一般也不会造成什么影响(虽然也不总是如此,比如用了APC之类)。

这些都是无状态带来的好处,可以降低开发和维护的成本,并通过堆硬件提高性能。抛弃一些东西,在其他方面就可以获得更多。

完全无状态的服务端类似一个巨大的纯函数,每个参数相同的请求都会获得相同的结果,也不对外部环境产生影响。但是如果真做到这个程度,服务端就变成静态了,失去其应有的作用。

因此我们还是需要一种手段,在外部保存数据,最好是基于文件的数据库。数据库用内存加速可以接受,但是完全依赖内存就会失去对意外宕机的抵抗力。其他临时性的数据,能省则省。包括 session,虽然 session 也可以用文件或数据库保存,但是我们可以通过使用 json web token ,把它也省了。服务器上的状态越少、维护越容易。

当然,在实际工作中,我也使用缓存,但仅限于特别关键的地方。缓存必须独立于自己开发的软件存在,并且往往是以单向的、即时计算的形式来生成。独立可以确保能在不同进程间共享;单向是指只有一种方法来计算缓存,如果要更新缓存,只能用相同的方法重新计算一次,而不允许对当前的缓存进行加减等操作,这样就算出现意外的并发,也不会导致缓存中的内容出现错误;即时计算是指在第一次需要某个值时,才对其进行计算,并将结果存入缓存,直到过期。如此一来,缓存也成了“无状态”的,缓存的内容不受计算次数的影响,宕机重启也不会影响软件的整体运行,缓存会在需要时各自重建。虽然这种做法没有将缓存的价值发挥到最大,但由于开发和维护成本极低,有很高的性价比。

Node.js 毕竟不是 PHP,要在 Node.js 和 Express 环境中做到完全的无状态有点费力不讨好,但是基本的思想可以借鉴,尽量减少服务端要维护的状态,并在模块的级别实现这一目标。

要做到这一点,最基本的一个要求,就是别让变量活过一个请求,Express 的每个请求最终都会对应到一个回调函数,这个函数里不能出现其他来自外部的变量(必要的第三方库和数据库连接池会出现在其中,但从整个模块角度看,它们应该算是不可变量)。如果你在整个模块中,都能只使用 const,不用 var 来完成所有功能,并且没有作弊(把 const 定义的对象下的属性当变量用),那么就基本达成无状态的目标了。

当你的模块实现了无状态。在性能方面,就可放心的使用 Cluster 来启动子进程扩展并发能力,请求无论落入哪个子进程,都不会影响返回的结果,如果在前面加上一道负载均衡,还可以进一步扩展到多台服务器;在开发和维护方面,你可以放心的使用热加载,通过监测文件变化,在不停止服务的情况下更新软件版本。粒度比使用 nodemon 或者 supervior 等工具更细。

转载于:https://my.oschina.net/xiongliding/blog/1553591

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108095.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 尺规作图:经过已知直线上的一点作这条直线的垂线_尺规作图过直线外一点作垂线

    尺规作图:经过已知直线上的一点作这条直线的垂线_尺规作图过直线外一点作垂线-

    2022年9月20日
    0
  • 小明加密通道进入_门禁系统跟闸机通道的区分是什么?功能是一样吗

    小明加密通道进入_门禁系统跟闸机通道的区分是什么?功能是一样吗门禁系统属于一卡通系统的范畴。它是以中央处理器为核心,由控制器、信息采集器和电控锁组成的控制网络系统。通过系统的信息读取和处理,实现了各种门锁开关的自动控制。根据信息阅读的方式可以分为:插卡式、感应式、图像检测式、双眼虹膜识别式等。他们的技术含量和体系工程预算顺序先后提高。且融合三辊闸、摆闸、翼闸等多种入口处监管设施,保持更智能。门禁用到ID和IC两种卡片,IC门禁有加密功能,存贮容量也大,广泛用…

    2022年6月11日
    62
  • STM32中重定向printf到SWO口[通俗易懂]

    STM32中重定向printf到SWO口[通俗易懂]Keil中调试:用SWO功能替代printf引用网址:http://blog.csdn.net/xiaolei05/article/details/8526021嵌入式软件开发中的一个基本需求就是能通过终端来输出调试信息,一般可通过2种方式实现:一种是使用串口线连接板上的UART和PC上的COM口,通过PC上的超级终端来查看调试信息;另一种则是采用半主机机制,但有可能不被

    2025年6月1日
    0
  • 使用reaver命令穷举PIN码破解WPA2-PSK加密的无线网络[通俗易懂]

    使用reaver命令穷举PIN码破解WPA2-PSK加密的无线网络[通俗易懂]【前言】现在的路由器大多都默认用WPA2-PSK方式对无线网络进行加密了,不能再像WEP加密方式那样好破解,使用字典又需要费心费力地整理字典,而且字典破解的效率还慢。所以我们需要更有效率的破解方法。好在现在大多数的路由器都提供WPS功能,通过这个功能,用户可以使用PIN码登录到路由器。但这个PIN码的长度只有8位,而且可能的取值只有11000种(注意,不是10…

    2022年6月4日
    30
  • vector初始化与清空[通俗易懂]

    vector初始化与清空[通俗易懂]vector初始化与清空vector初始化vector<int>v;如果直接进行访问v[i]会报错解决方案:可以使用v.resize(n)或者v.resize(n,m)来初始化,前者是使用n个0来初始化,后者是使用n个m来初始化。vector清空//1.clear,清空元素,但不回收空间v.clear();//2.swap,清空元素并回收内存vector<int>().swap

    2022年9月16日
    0
  • 数据库六大范式(数据库一范式二范式怎么区分)

    1.第一范式(1NF):在关系(表)中,列(属性/字段)不可再分1.每一列属性都是不可再分的属性值,确保每一列的原子性2.两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据2.第二范式(2NF)消除了非主属性对于主属性的部分函数依赖属性完全依赖于主键。第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的

    2022年4月15日
    73

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号