- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
作为前端,我们知道 node 在 构建 方面是成功的,我们也听说过全栈,那么 node 是否能应用在 企业级的后端 ?一起来看一下 腾讯视频的 NodeJs 改造 .
Tip : 故事大概是 2018 年,主角 杨浩 ,来源于:
腾讯视频是一个 内容型 的网页.
在 2014 年以前使用的是 C++ 动态生成页面。有两个问题:
于是打算使用 NodeJs 来对其进行改造.
由于腾讯视频是 内容型 的网页,当时有 30% 的流量来自搜索引擎,所以需要更好的 SEO,于是选用 SSR(服务器渲染).
Tip : Vue_SSR 中也提到服务端渲染的优势:更快的首屏加载、更好的 SEO 。
NodeJs 扮演的角色如下:
请求经过 cdn,经过 nginx 通过负载均衡访问 NodeJs 服务,NodeJs 从各个后台服务拉取数据,渲染好了在返回给前端.
Tip :相当于以前用 c++ 生成页面,现在由 NodeJs 生成页面.
rpc (作用类似 http 协议) 就是远端资源调用,因为 node 需要从各个后台服务拉取数据。这里涉及4个方面的事情:
负载均衡
。node 和后台服务之间有一层负载均衡,用的是一种类 DNS负载均衡
,所以得和负载均衡服务交互,拿到每次需要访问服务器的ip Mongo/mysql/redis
(redis - 基于键值对的 内存数据库
) 存储的打通。比较简单,就是对应 npm 包的使用 后台私有协议
。例如二进制的协议某场景下比http协议好一些 Tip : DNS除了能解析域名之外还具有负载均衡的功能 。
node 是单线程,使用 cluster 模块创建多个 Nodejs 进程,实现高并发和高可用性。但 cluster 还有点缺陷,做了以下几点优化:
心跳
- master 定时给 cluster 发信息,如果有回复说明它还活着,否则就是僵死,就 kill 它 内存检测
- 监控 cluster 内存,如果内存过高,可能就是内存泄漏,也杀死它 重启
- cluster kill 后,有的应用可能不能用,就需要将其重启 Tip :在 Node.js 中, cluster 模块提供了一种简单的方式来创建多个 Node.js 进程,以实现高并发和高可用性。通过集群模块,开发者可以使用现有的单线程程序代码,并将其自动拆分到多个子进程中执行,从而充分利用 CPU 和内存资源,提高应用的效率和稳定性.
终于把 Node 打通了,现在可以用 node 写点东西了.
要用 node 写一个稳定的服务,也不是那么简单。node 很容易挂掉,比如一点语法问题.
懂前端的人很多,但懂 node 的就相对要少。写后端需要懂后端那套东西,要会服务器调优,还要懂运维.
为了解决 Node 人员不足 ,决定使用 框架 来平滑 node 曲线.
之前要用 node 写项目难度大,是因为需要经历这4步: 业务逻辑 -> 会写 NodeJs -> 熟悉 rpc 调用 -> 熟悉运维(性能调优) 。
现在用框架,只需要写 业务逻辑 就能开干.
这里框架主要使用 配置化 ,屏蔽底层复杂的实现,对外暴露友好的配置。就像 webpack ,让前端构建生态非常繁荣.
要做 配置化 ,就得分析 ssr 本质:从各个后台领取数据,简单处理后进行渲染.
ssr抽象表示: 请求参数 -> 后端数据 + 模板 -> 页面文本 。
ssr 公式:内容=f(数据源,模板) 。
只要将 数据源 和 模板 配置化,就可以通过一个函数解决 ssr 的问题.
研究了如下几种模板:
art-template 中的 forEach 可以使用 预编译语法 来实现,由于交互较少,所以无需使用 vue和react。而且 es6 模板速度测试比 vue-server-render 快很多.
所以最终选取第二种方案: es6 template .
数据源的配置用如下一个 json 表示:
module.exports = {
video: {
url: "http://...."
},
vidviewcount: {
dependencies: ['video'],
url: "protobuf://union.video.qq.com/...."
},
rank: {
url: "redis://admin:admin@135246:65535/get?key=haha"
}
}
这个 json 表示 ssr 过程中数据获取逻辑,其中 vidviewcount 通过 dependencies 字段指明依赖 video.
这里用 http、protobuf、redis三种 协议 (方式)获取数据。一个协议对应一个请求器,不在框架中的协议可以注册即可。就像这样:
factory.registerRequestor('http', requestor);
function requestor(){
...
}
为了增加配置的灵活性,这里增加了几个 hook:
{
...
fixBefore: function(param){
// 检测参数合法性
return param
},
fixAfter: function(data){
// 检测返回数据合法性
if(!data.vid){
throw Error('xxx')
}
return data
},
onError: function(e){
return err;
}
}
只要学会写配置就能搞定 ssr 逻辑.
公式:内容= f(数据源,模板)(参数) 。
ssr 外部用 koa(nodejs 的web框架) 封装一下就是一个服务:
let app = koa()
let ssr = pigfarm(data, template)
app.use(async ctx => {
ctx.body = await ssr(ctx.query)
})
后台有后台擅长的地方(逻辑、计算密集),前端有前端擅长的地方(前端网页优化).
寻找一个 合作共赢 的方式。这里做了如下几个有特色的前端服务:
每次业务逻辑的改动需要经历长时间的 发布 和 重启 。
前面已经将 数据源 和 模板 做到了 配置化 ,现在修改逻辑,只需要更改数据库中的数据源和模板即可,做到热更新.
v.qq.com 首页包含27个模块 。
利用 transfer-encoding:chunked 快速返回首屏数据,后面再加载2、3、4...屏的数据 。
Tip :BigPipe 是一个前端性能优化技术,采用分块渲染的方式。 transfer-encoding:chunked 是一种 HTTP协议中定义的传输编码方式之一。运行服务器在不知道响应体大小的情况下,将响应分成若干个固定大小的快进行传输.
前端容灾是指在前端应用中,为了保障可靠性和稳定性而采用的一系列技术和策略,以确保即使在系统出现部分异常或错误的情况下,仍然可以正常提供服务。比如网络问题、服务器故障等 。
这里可以做 整页备份 .
js 中用高阶函数非常容易实现缓存。请看示例:
function memoize(func) {
// 用于缓存
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
// 如果缓存中有值,直接返回
if (cache[key]) {
return cache[key];
}
const result = func.apply(this, args);
cache[key] = result;
return result;
};
}
最后此篇关于NodeJs实践之他说的文章就讲到这里了,如果你想了解更多关于NodeJs实践之他说的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
本文分享自华为云社区《大模型LLM之分布式训练》,作者: 码上开花_Lancer。 随着语言模型参数量和所需训练数据量的急速增长,单个机器上有限的资源已无法满足大语言模型训练的要求。需要设计分布式训
本文分享自华为云社区《五大基础算法--动态规划法》,作者: 大金(内蒙的)。 一、基本概念 动态规划法,和分治法极其相似。区别就是,在求解子问题时,会保存该子问题的解,后面的子问题求解时,可以直接拿来
pip install scp pip install pexpect 测试代码: import os import stat import paramiko # 用于调用scp命令 def s
我目前正在实现“ token ”REST 服务。 token 只是一个字符串,由一些参数构建而成,然后经过哈希处理并在一定时间后过期。 我想在我的 REST 服务中有一个可以验证 token 的端点,
打开软删除后,我在客户端上添加一条记录,推送,删除添加的记录推送,然后尝试使用与初始记录相同的主键添加新记录(然后推送),我得到一个异常(exception)。 EntityDomainManager
打开软删除后,我在客户端上添加一条记录,推送,删除添加的记录推送,然后尝试使用与初始记录相同的主键添加新记录(然后推送),我得到一个异常(exception)。 EntityDomainManager
我有一个应用程序,每 x 秒接收一次天气信息。我想将此数据保存到 XML 文件中。 我应该为每个天气通知创建一个新的 XML 文件,还是将每个通知附加到同一个 XML 文件中?我不确定 XML 标准的
我猜我们大多数人都必须在某个时候处理这个问题,所以我想我会问这个问题。 当您的 BLL 中有很多集合并且您发现自己一遍又一遍地编写相同的旧内联(匿名)谓词时,显然有必要进行封装,但实现封装的最佳方
我有一些 c# 代码已经运行了一段时间了..我不得不说,虽然我了解 OO 原则的基础知识,但显然有不止一种方法可以给猫剥皮(尽管我讨厌那个短语!)。 因此,我有一个基本抽象类作为基本数据服务类,如下所
我设计了一个 SQL 数据库系统(使用 Postgre),我有一个问题,即创建一个关系/引用的常见做法是什么,这种关系/引用即使在引用的对象被删除时也能持续存在。 比如有一个UserORM,还有Act
我们的目标是搜索用户输入的字符串并计算在其中找到多少元音。不幸的是我被困在这里,有什么帮助吗? def numVowels(s): vowels= "AEIOUaeiou" if s
我有一个适用于我的“items”int 数组的旋转函数。下面的代码完成了它,除了我不必要地传输值。我正在努力实现“就地”轮换。我的意思是 ptrs 会递增或递减,而不是从数组中获取值。我需要通过这种方
我有一个 json 存储在我的应用程序文档文件夹中,我需要在我的所有 View 中使用它。我正在加载 json 并将其添加到每个 View 中的 NSMutableArray。但现在我了解到,我可以将
我用 C++ 开始了一个项目。这种语言的内存管理对我来说是新的。 我过去常常使用 new () 创建对象,然后传递指针,虽然它可以工作,但调试起来很痛苦,人们看到代码时会用有趣的眼神看着我。我为它没有
已结束。 这个问题是 off-topic .它目前不接受答案。 想要改进这个问题? Update the question所以它是on-topic堆栈溢出。 关闭 10 年前。 Improve thi
保持类松散耦合是编写易于理解、修改和调试的代码的一个重要方面——我明白这一点。然而,作为一个新手,几乎任何时候我都会超越我所苦苦挣扎的最简单的例子。 我或多或少地了解如何将字符串、整数和简单数据类型封
我发现我需要编写大量重复代码,因为我无法从其他 Controller 调用函数。例如,这里新闻提要内容在我的代码中重复,我对一个 Controller 做一些特定的事情,然后需要像这样加载我的新闻提要
假设需要一种数字数据类型,其允许值在指定范围内。更具体地说,假设要定义一个整数类型,其最小值为0,最大值为5000。这种情况在很多情况下都会出现,例如在对数据库数据类型,XSD数据类型进行建模时。 在
假设我想循环整个数组来访问每个元素。使用 for 循环、for...in 循环或 for...of 循环是 JavaScript 开发人员的标准做法吗? 例如: var myArray = ["app
我有一个旧的 SL4/ria 应用程序,我希望用 Breeze 取代它。我有一个关于内存使用和缓存的问题。我的应用程序加载工作列表(一个典型的用户可以访问大约 1,000 个这些工作)。此外,还有很多
我是一名优秀的程序员,十分优秀!