未加星标

使用nodejs做模板渲染引擎服务

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二03 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

对于一个有追求的IT,会不断的追求网站性能,更不用说,直接面对用户的网站,特别担心高峰流量。为了快速迭代我们,初期使用php,后来核心逻辑切换到go,php只是渲染模板。

最近我一段时间,一直感觉php性能差,也有可能是我心里的原因,我就想换到php,使用其他的方式,终于有一天,突然想到,我是否可以用户访问go,然后使用nodejs来渲染模板。趁着周六没人,自己会公司鼓捣。

欣喜若狂

我搜索发现这么一个地址https://github.com/baryshev/template-benchmark,介绍了各个开源模板引擎,以及渲染10万模板的耗时。我自己克隆下来,发现自己的电脑,比这个数据还好一些。都是一些小的模板并且不转义的情况下,1秒可以渲染100万的模板。我自己初步估计,如果模板大一些,即使下降到10万的模板,也是非常不错的。

在监控CPU利用率的情况下,发现只有单核CPU跑满了100%。我的电脑有8核,我使用taskset命令,强制将进程绑定到某个CPU,同时开了4个进程,4个核都满了,时间没有变慢。这么说,我8个核应该1秒,可以渲染80万的模板。

表现还不错

既然有这么好的性能,应该可以做成独立服务。go和nodejs通信可以使用长连接,也可以使用短连接。为了快速,我使用了短连接,http协议进行通信。

我初步写了一个简单的nodejs web 服务,使用ab压力单个端口,可以压到1万。如果开了多个进程,应该至少可以压到4万。

var http = require("http");
var i = 0;
var arguments = process.argv;
var dot = require('dot');
var data = require('./checkout');
var fs = require('fs');
var str = fs.readFileSync('./dot/tpl_unescaped.dot', 'utf8');
compiled = dot.template(str)
http.createServer(function(request, response) {
console.log('request received ' + i++);
response.writeHead(200, { "Content-Type": "text/plain" });
response.write('hello world');
response.end();
}).listen(arguments[2]);
prepareUnescaped = function(data) {
return compiled(data);
};
console.log('server started, port is ' + arguments[2]);

然后,我就用GO简单写了http连接。

package main
import (
"io/ioutil"
"log"
"net"
"net/http"
"strconv"
"time"
"os"
"runtime"
)
var Total = 100000
var errNum = 0
var threads = 100
var transport = &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, time.Millisecond*200) //设置建立连接超时
if err != nil {
return nil, err
}
c.SetDeadline(time.Now().Add(time.Millisecond * 300)) //设置发送接收数据超时
return c, nil
},
}
func main() {
f, _ := os.OpenFile("testlogfile", os.O_RDWR|os.O_CREATE, 0666)
defer f.Close()
log.SetOutput(f)
runtime.GOMAXPROCS(runtime.NumCPU() - 1)
runTest()
}
func runTest() {
log.Println("begin")
var i = 0
var startTime = time.Now().UnixNano()
chs := []chan int{}
var threadId = 0
for ; threadId != threads; threadId = threadId + 1 {
ch := make(chan int)
chs = append(chs, ch)
go func(threadId int) {
for ; i <= Total; i = i + 1 {
var index = i
var port = index%8 + 8120
var startTime = time.Now().UnixNano()
_, err := getResponse(strconv.Itoa(port))
var endTime = time.Now().UnixNano()
log.Println("lost time :", (endTime-startTime)/1000000)
if err != nil {
errNum = errNum + 1
//log.Println("thread :", threadId, ";port:", port, ";index:", index, ";error:", err.Error())
} else {
//log.Println("thread :", threadId, ";port:", port, ";index:", index, "; msg:", str)
}
}
ch <- 0
}(threadId)
}
for _, ch := range chs {
<-ch
close(ch)
}
var endTime = time.Now().UnixNano()
log.Println("lost time :", (endTime-startTime)/1000000)
log.Println("err num", errNum)
}
func getResponse(port string) (string, error) {
req, err := http.NewRequest("GET", "http://10.236.103.101:"+port, nil)
if err != nil {
return "", err
}
//client := &http.Client{Transport:transport}
client := &http.Client{}
resp, perr := client.Do(req)
if perr != nil {
return "", perr
}
defer resp.Body.Close()
bodyByte, rerr := ioutil.ReadAll(resp.Body)
if rerr != nil {
return "", rerr
}
return string(bodyByte), nil
}

如果连接本地的nodejs,100万请求,开启了500个goroutine,设置连接和读超时时间都是设置1秒,需要耗时53.7秒,平均每秒处理18621个请求。

如果远程访问,100万请求,开启1000个goroutine, 设置连接和读超时时间都是设置1秒,需要耗时44秒,平均每秒处理,22727个请求。

看了一下每一个请求的耗时,TP99在60ms左右,耗时确实有一些长了。

性能大降

看着刚才的数据表现还不错,我就选择dot这个渲染模板引擎,然后把一段简单的模板拷贝复制到200行。

<html>
<head>
<title>{title|s}</title>
</head>
<body>
<p>{text|s}</p>
{#projects}
<a href="{url|s}">{name|s}</a>
<p>{description|s}</p>
{/projects}
{^projects}
No projects
{/projects}
</body>
</html>

使用go继续测试,本地连接的方式,每秒处理2000个请求,性能直接下降10倍,难以接受。使用了远程连接,每秒处理请求更少,最后发现网卡打满了,就放弃了这个测试。TP90的时候,170毫秒。

有点不太死心,或许是我go没有优化,于是使用了ab继续测试,单压一个端口,差不多3000个请求,TP90是100ms。

如果真的是2000话,那就没有必要做了。不过和ab比起来,性能还是差很多,还得仔细的查找原因,到底因为什么。

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: CPU开源数据Head
分页:12
转载请注明
本文标题:使用nodejs做模板渲染引擎服务
本站链接:http://www.codesec.net/view/532522.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(102)