NodeJs 实践之他说

科技资讯 投稿 22600 0 评论

NodeJs 实践之他说

NodeJs 实践之他说

构建方面是成功的,我们也听说过全栈,那么 node 是否能应用在企业级的后端?一起来看一下腾讯视频的 NodeJs 改造

Tip: 故事大概是 2018 年,主角杨浩,来源于:

背景

内容型的网页。

    前端不太会维护 C++ 的那套东西
  • C++ 定时生成网页。有多少个视频,它就会生成多少个网页,然后推送到对应的服务器中。如果更改了某个视频的信息,得等到下次生成网页才会更新

于是打算使用 NodeJs 来对其进行改造。

第一只怪 - 打通 NodeJs

内容型的网页,当时有 30% 的流量来自搜索引擎,所以需要更好的 SEO,于是选用 SSR(服务器渲染)。

Tip: Vue_SSR中也提到服务端渲染的优势:更快的首屏加载、更好的 SEO

Tip:相当于以前用 c++ 生成页面,现在由 NodeJs 生成页面。

打通 RPC 调用

    负载均衡。node 和后台服务之间有一层负载均衡,用的是一种类DNS负载均衡,所以得和负载均衡服务交互,拿到每次需要访问服务器的ip
  • Mongo/mysql/redis(redis - 基于键值对的内存数据库) 存储的打通。比较简单,就是对应 npm 包的使用
  • 后台私有协议。例如二进制的协议某场景下比http协议好一些
  • 监控系统/日志系统

Tip: DNS除了能解析域名之外还具有负载均衡的功能

高并发下进程管理

    心跳 - master 定时给 cluster 发信息,如果有回复说明它还活着,否则就是僵死,就 kill 它
  • 内存检测 - 监控 cluster 内存,如果内存过高,可能就是内存泄漏,也杀死它
  • 重启 - cluster kill 后,有的应用可能不能用,就需要将其重启

Tip:在 Node.js 中,cluster 模块提供了一种简单的方式来创建多个 Node.js 进程,以实现高并发和高可用性。通过集群模块,开发者可以使用现有的单线程程序代码,并将其自动拆分到多个子进程中执行,从而充分利用 CPU 和内存资源,提高应用的效率和稳定性。

第二只怪 - 维护 NodeJs

要用 node 写一个稳定的服务,也不是那么简单。node 很容易挂掉,比如一点语法问题。

Node 人员不足

为了解决 Node 人员不足,决定使用框架来平滑 node 曲线。

业务逻辑 -> 会写 NodeJs -> 熟悉 rpc 调用 -> 熟悉运维(性能调优)

业务逻辑就能开干。

配置化,屏蔽底层复杂的实现,对外暴露友好的配置。就像 webpack,让前端构建生态非常繁荣。

配置化,就得分析 ssr 本质:从各个后台领取数据,简单处理后进行渲染。

请求参数 -> 后端数据 + 模板 -> 页面文本

只要将数据源模板配置化,就可以通过一个函数解决 ssr 的问题。

模板引擎的选型

    art-template 国内有名的开源模板引擎
  1. es6 template string + vm.runInNewContext(编译和运行代码,作用类似 new Function('console.log("1"')
  2. vue ssr、react ssr

art-template 中的 forEach 可以使用预编译语法来实现,由于交互较少,所以无需使用 vue和react。而且 es6 模板速度测试比 vue-server-render 快很多。

es6 template。

数据源

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。

协议(方式)获取数据。一个协议对应一个请求器,不在框架中的协议可以注册即可。就像这样:

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 逻辑

只要学会写配置就能搞定 ssr 逻辑。

f(数据源,模板(参数

let app = koa(
let ssr = pigfarm(data, template
app.use(async ctx => {
    ctx.body = await ssr(ctx.query
}

第三只怪 - 抢后端饭碗的问题

后台有后台擅长的地方(逻辑、计算密集),前端有前端擅长的地方(前端网页优化)。

合作共赢的方式。这里做了如下几个有特色的前端服务:

热更新

发布和重启

数据源和模板做到了配置化,现在修改逻辑,只需要更改数据库中的数据源和模板即可,做到热更新。

首页调优

    富含个性化内容,无法缓存
  • 页面庞大,速度慢
  • 全网页超过40个rpc
  • 个性化接口调用慢

利用 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 实践之他说

赞同 (98) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽