作为前端,我们知道 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负载均衡
,所以得和负载均衡服务交互,拿到每次需要访问服务器的ipMongo/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;
};
}
大家好,又见面了,我是你们的朋友全栈君。使用Java的Scanner类nextLne()方法从显示器输入数据时,nextInt()后面的nextLine()直接跳过没有执行;截图:第三个输入直接跳过通过上网的查找我终于发现了问题出在哪里:原来nextLine()函数获取的是一整行的内容其中也包括了(\n)也就是换行符而nextInt()函数获取的仅仅是一个值不包含(\n),那么nextInt()后面的nextLine()读取一行,就把(\n)读进去了,意思就是nextLine()的值是(\n),所以不会进行数据获取。解决办法:可以选择多添加一个nextLine()去获取nextInt()后面的换行符(\n)改了之后程序正常输入:[03]java中的方法以及控制语句00Java中的语句块语句块(有时叫做复合语句),是用花括号扩起的任意数量的简单Java语句.块确定了局部变量的作用域.块中的程序代码,作为一个整体,是要被一起执行的.块可以被嵌套在另一个块中,但…Java中的方法应用一.如何定义java中的方法所谓方法,就是用来解决一类问题的代码的有序
大家好,又见面了,我是全栈君__format__()方法 __format__()传参方法:someobject.__format__(specification) specification为指定格式,当应用程序中出现”{0:specification}”.format(someobject)或format(someobject,specification)时,会默认以这种方式调用 当specification为”“时,一种合理的返回值是returnstr(self),这为各种对象的字符串表示形式提供了明确的一致性 注意,”{0!s}”.format()和”{0!r}”.format()并不会调用__format__()方法,他们会直接调用__str__()或者__repr__()例:自定义我们自己的__format__()格式#coding=utf-8 classformatest: def__init__(self,name,age): self.name,self.age=name,age def__format__(self,specification): ifs
一、github地址:https://github.com/liyinchigithub/Omysql二、效果三、使用方式如果你电脑已经安装配置Git、node环境,可以直接按下面步骤进行操作:1、从github拉取工程gitclonegit@github.com:liyinchigithub/express-mysql-restfulAPI.git复制2、切换到目录下cdOmysql复制3、安装依赖包npminstall复制4、启动omysql服务nodeserver.js复制5、如果你的电脑还没有node环境,具体配置方法可以参考下面两个链接:windowshttps://jingyan.baidu.com/article/1876c8529c79e2890b1376dd.htmlmachttps://jingyan.baidu.com/article/6b1823098bdd9fba59e1597a.html在postman上面构建以下请求,即可实现postman访问数据库!API接口文档1、功能创建数据库请求方法:POST 请求地址: http://127.0.0.1:8004
captcha是CompletelyAutomatedPublicTuringTesttoTellComputersandHumansApart,全自动区分计算机和人类的图灵测试)的简称。登陆失败若干次之后,豆瓣登录页面才会出现验证码。所以为了确保py文件运行正确,要先故意输错几次,出现验证码框之后,再运行。:)登录界面使用Python3.6。fromurllib.requestimporturlretrieve importrequests frombs4importBeautifulSoup fromosimportremove try: importcookielib except: importhttp.cookiejarascookielib try: fromPILimportImage except: pass url='https://accounts.douban.com/login' datas={'source':'index_nav', 'remember':'on
1、a、安装vant:npmivant-S b、按需引入组件:安装webpack插件:babel-plugin-import //在当前项目下安装:npminstallbabel-plugin-import-D//.babelrc中配置 //注意:webpack1无需设置libraryDirectory { "plugins":[ ["import",{ "libraryName":"vant", "libraryDirectory":"es", "style":true }] ] } //对于使用babel7的用户,可以在babel.config.js中配置 module.exports={ plugins:[ ['import',{ libraryName:'vant', libraryDirectory:'es', style:true },'vant'] ] };//在mian.js或者需要的组件中引入所需的组件 import{Button,Cell}from'vant';复制 2、实现下拉刷新上拉加载:<van-pull-refresh
seq2seq的用途有很多,比如机器翻译,写诗,作曲,看图写文字等等用途很广泛!该模型最早在2014年被Cho和Sutskever先后提出,前者将该模型命名为“Encoder-DecoderModel”也就是编码-解码模型,后者将其命名为“SequencetoSequenceModel”也就是序列到序列模型,两者有一些细节上的差异,但总体大致思想基本相同。 seq2seq根据字面意思来看就是序列到序列,再具体点就是输入一个序列(可以是一句话,一个图片等)输出另一个序列。这里以RNN为基础的机器翻译为例,介绍seq2seq和attention注意力机制。(seq2seq实现的方法有很多,比如MLP,CNN,RNN等) 这是机器翻译的部分数据(法语->英语): 我们先了解下机器翻译的大致流程: 大致意思就是根据输入的文本,神经网络开始学习和记忆,这个就是所谓的Encoder编码过程;然后根据自己的记忆,把文本一一翻译出来,这个就是所谓的Decoder解码过程。 现在再让我们更进一步了解seq2seq的具体流程:
1SpringBoot整合Redis 1导入依赖 创建SpringBoot项目时不要乱选默认开发工具,有一个坑 <!--若创建时已选择,则不用导入--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 复制 2编写配置文件 #配置redis #Redis服务器地址 spring.redis.host=192.168.0.108 #Redis服务器连接端口 spring.redis.port=6379 #使用数据库的索引编号,一个示例有16个数据库0到15 spring.redis.database=0 #Redis服务器连接密码(默认为空) spring.redis.password= 复制 3定制RedisTemplate的模板 com/yu/config/RedisConfig @Configur
本文档以iMX6UL为例,简单介绍cpufreq的5种模式。 在imx6ul的menuconfig中,进入 CPUPowerManagement---> CPUFrequencyscaling---> DefaultCPUFreqgovernor(ondemand)---> 中,如下图所示,可以看到有5个选项。这5个选项,可以将cpu的频率设置为不同的 管理模式,默认设置的是ondemand模式。 cpufreq是一个动态调整cpu频率的模块,系统启动时会生成 “/sys/devices/system/cpu/cpu0/cpufreq/”,如下图所示,是imx6ul文件上的 cpufreq文件夹。 以上参数可以通过cat命令,例如: “cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor”可以获取当前 CPU频率的模式。作者机器当前模式是“ondemand”,也就是动态调频模式。 其它参数: cpuinfo_cur_freq为当前频率;
shutdown执行过程: shutdown命令是用shell编写的程序,必须由超级用户才能执⾏。 shutdown命令执行后,会以广播的形式通知正在系统中工作的所有用户,系统将在指定的时间内关闭。请保存文件,停止作业,注销用户。此时login指令被冻结,新的用户不能登录。当所有用户从系统中注销或者指定时间已到时,shutdown就发送信号给init程序,要求init程序改变系统运行级别。接着,init程序根据shutdown指令传递过来的参数,相应地改变运行级别。例如,如果shutdown指定的参数是关机命令,init程序就执行nit0进行关机;如果shutdown指定的参数要重启系统,init程序就执行init6进行系统重启。 shutdown命令的详细语法如下: shutdown[-fFhknrc(参数名称)][-t秒数]时间[警告信息]各参数含义如下。 各参数含义如下 -f:重新启动时不执行fsck。 -F:重新启动时执行fsck。 -h:将系统关机,在某种程度上功能与halt命令相当。 -k:只是发送信息给所有⽤户,但并不会真正
项目:关灯游戏,所用软件,pygame成员:祁昊,刘孝东 关灯游戏设计文档: pygame作为一种游戏编程语言,以其简单性、可移植性等优点,得到了广泛地应用,特别是py使用比c,c++等语言简便,使其成为网络编程首选编程语言。,Pygame是跨平台Python模块,专为电子游戏设计。基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python。工具tile编辑器和一个关卡编辑器。得到广大程序员的接受和认可。 “关灯游戏”是大众化的一个小程序,人们手机中是一个很常见的一个小游戏,人们 对它并不陌生,在紧张的现在生活中给人们带来了不少的乐趣,我们写的这 个关灯小游戏可以让人们业余时间的适当放松,再繁忙的生活节奏中适当的放松下来。在这个程序中我用了python语言来编写,运用了python中的一些常用的功能,python语言是在国内外广泛使用的一种语言。python语言功能丰富、表达能力强、使用灵活方便、应用面广、目标程序效率高、可移植性好,纯粹的面向对象的编程,特别适合用于编写应用软件。代码简单易懂,在游戏的同时
解决Element-u的el-form使用v-if校验失灵问题 在element-ui的校验过程中,鉴于使用自带的校验方式,繁琐且麻烦,因而使用了element-ui-verify的插件。但是现在碰到一个新的问题,不知道具体是哪块问题,看了两个的源码,想使用element-ui自带的addFields时,无法生效,因而是内部方法,外部无法拿到【此处先记一笔,看看后期这块是否是解决的要点】。 主要出现的问题是,使用了v-if时,导致无法有效被element-ui知晓,而报[ElementWarn]pleasepasscorrectprops!,意思就是说使用v-if的字段无法及时被收录。而这个是概率问题,有时候可以有时候不行。目前还无法有效判断出来。 <templatev-if="editMobile"> <el-rowtype="flex":gutter="2"v-if="editMobile"> <el-col:span="20"> <el-form-item ref="captcha" label="验证码:" prop="captcha"
暴力70分能拿到,100分不能 知识点: 了解到差分的思想,现在认为如果用到了一个数组来记录区间变化量,则可称为差分。 unique函数:【整理】C++中的unique函数-nimphy-博客园(cnblogs.com) 参考别人的文章后自己写,第一次没过。 原因是 for(inti=1;i<n-1;i++){ if(a[i-1]<a[i]&&a[i]>a[i+1]){ cnt[a[i]]++; } else{ cnt[a[i]]--; } }复制 else判断条件错误,应该是 for(inti=1;i<n-1;i++){ if(a[i-1]<a[i]&&a[i]>a[i+1]){ cnt[a[i]]++; } elseif(a[i-1]>a[i]&&a[i]<a[i+1]){ cnt[a[i]]--; } }复制 什么是“山峰”“山谷”当时没搞清楚 AC代码: #include<iostream> #include<algorithm> #i
-sed过滤行 sed'2p' sed'2,5p' sed'2p;3p;4p' -awk过滤行 awk'NR==2' awk'NR>=2&&NR<=3' awk'NR==2||NR==3||NR==4' -awk条件过滤 awk'{if($3>10)print$0}' 复制 过滤某1行 sed过滤第2行 [root@n1~]#sed-n'2p'/etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin 复制 awk过滤第2行 [root@n1~]#awk'NR==2'/etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin 复制 过滤2<i<4行 sed过滤2<i<4行 [root@n1~]#sed-n'2,4p'/etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin 复制 aw
主: 修改配置文件: [mysqld] log-bin=mysql-bin server-id=1 账户授权 mysql>GRANTREPLICATIONSLAVEON*.* TO'rep'@'%'IDENTIFIEDBY'Passw0rd'; 锁表,保持一致性 mysql>FLUSHTABLESWITHREADLOCK; 备份数据库 shell>mysqldump-uroot-pPassw0rd--all-databases>toslave.sql 读取日志名和偏移量 mysql>SHOWMASTERSTATUS; 重新启用写活动: mysql>UNLOCKTABLES; 拷贝toslave.sql至从服务器 scptoslave.sqlroot@10.210.74.49 修改从服务配置文件 [mysqld] server-id=2 启动从服务器 用--skip-slave-start选项启动从服务器,以便它不立即尝试连接主服务器。 /bin/mysqld_safe--
一.EGL前言 二.EGL绘制流程简介 三.eglCreateWindowSurface函数简介 1.eglCreateWindowSurface函数 2.EGLSurface分类 四.eglCreateWindowSurface函数使用 五.猜你喜欢 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLES基础 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLES特效 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLES转场 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLES函数 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLESGPUImage使用 零基础OpenGLES学习路线推荐:OpenGLES学习目录>>OpenGLESGLSL编程 一.EGL前言 EGLNativeDisplayType–系统显示类型,标识你所开发设备的物理屏幕,DX/OPenGL
Fromhttp://www.addictivetips.com/mobile/how-to-change-customize-create-android-boot-animation-guide/ HowToChange,Customize&CreateAndroidBootAnimation[Guide] byHaroonQRajaonMay19,2011 55 ThebootanimationisthefirstthingthatyouseewhenpoweringonyourAndroidphoneortablet,aftertheoperatorormanufacturerlogo.Althoughitdoesnotserveapurposefunctionally,aneye-catchingbootanimationcancertainlymakeyourdevicestandoutwhilebooting.InthisthirdinstallmentofourAndroidcustomizationseries,w
确认binarylogs是否开启 showbinarylogs 如果没有启动注意在my.cnf的mysqld节中开启 log-bin=mysql-bin /mysql/bin/mysqlbinlogmysql-bin.000014 检查要恢复数据的起始时间(14:35:50)和截止时间(14:36:13) DELIMITER/*!*/; #at4 #20102914:35:50serverid1end_log_pos120CRC320x33a2b7cfStart:binlogv4,serverv5.6.49-logcreated20102914:35:50atstartup #Warning:thisbinlogiseitherinuseorwasnotclosedproperly. ROLLBACK/*!*/; BINLOG' xmKaXw8BAAAAdAAAAHgAAAABAAQANS42LjQ5LWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAADGYppfEzg
一、环境配置 1.brew下载||输入命令: /usr/bin/ruby-e"$(curl-fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install)" 复制 2.git下载||输入命令: brewinstallgit 复制 3.nodejs下载||输入命令: brewinstallnode 复制 4.检查git、nodejs版本 git--version node-v 复制 二、hexo 5.安装hexo sudonpminstall-ghexo-cli 复制 6.初始化hexo hexoinithexo 复制 7.进入到hexo文件夹下 cdhexo npminstall 复制 8.开启hexo服务器。 hexos 复制 浏览器中输入:localhost:4000,页面如图所示,hexo本地配置成功。 三、关联github 9.创建仓库。登录到自己到github账号,新建仓库,仓库名为:用户名.http://github.io,如图所示。10.进到hexo文件夹下
原文地址:SVN服务器搭建和使用(一)-xjbest-博客园http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407610.html Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说.首先来下载和搭建SVN服务器.现在Subversion已经迁移到apache网站上了,下载地址:http://subversion.apache.org/packages.html这是二进制文件包的下载地址,你可在左侧的导航栏找到源代码,文档的下载地址.windows操作系统下面的二进制文件包一共有5种,如图:个人认为最好用VisualSVNserver服务端和TortoiseSVN客户端搭配使用.点开上面的VisualSVN连接,下载VisualSVNserver,如图:然后下载TortoiseSVN客户端,官网下载地址:http://tortoisesvn.net/downloads.html注意下载跟你电脑匹配的安装包,在页面的下面你还可以找到语言包,如图:下载完成后,应该有这些安装包,如图:To