开发这个模块,是为了解决项目中的实际问题,思考设计的 。

本文原文连接: http://blog.csdn.NET/freewebsys/article/details/16944917 转载请注明出处!

前言:

参考了下ngx_lua,Node.js,PHP三个进行的压测对比。
http://bluehua.org/demo/php.node.lua.html

ngx_lua   Time per request: 3.065 [ms]
Node.js   Time per request: 3.205 [ms]
PHP      Time per request: 5.747 [ms]

从各种性能测试来说ngx_lua似乎在CPU和内存上更胜一筹,同时
ngx_lua出奇的资源消耗比较稳定,不像php那样波动比较大。
ngx_lua和Node.js几乎比php快接近1倍。
同时ngx_lua模型也是单线程的异步的事件驱动的,工作原理和nodejs相同,
代码甚至比nodejs的异步回调更好写一些。
对于ngx的运维和配置相对比nodejs来说更加熟悉和有经验。

1,总体设计思路

完全基于nginx层实现,nginx要开启ssi。
(Server Side Includes: http://wiki.nginx.org/HttpSsiModule )
以最快的速度展示页面,使用ssi直接读取数据,不是ajax返回。
服务端使用lua读取数据库内容并显示。

对应用的评论,使用mysql分区,按照itme_id进行hash。
设置成1024个分区,以后方便进行拆库。保证每一个表的数据都不是很大。
(1024)是mysql能设置的最大分区数量。

流程:

ningx 请求 /blog/201311/127.html(博客内容已经静态化了。)

使用ssi将url里面的参数获得调用lua评论模块

lua评论模块,读取数据库。(如果压力大,可以进行拆库,做cache)

2,主要代码

  1. local mysql= require("resty.mysql")
  2. --评论查询.
  3. local function query_mysql(sql)
  4. local db = mysql:new()
  5. db:connect{
  6. host = "127.0.0.1",
  7. port = 3306,
  8. database = "test",
  9. user = "root",
  10. password = "root"
  11. }
  12. local res, err, errno, sqlstate = db:query(sql)
  13. --使用数据库连接池。保持连接.
  14. db:set_keepalive(0, 100)
  15. return res
  16. end
  17. local comment_li = [[
  18. <li id="cmt_" class="row_1">
  19. <table width=""><tr>
  20. <td class="portrait">
  21. <a href="" name="rpl_277051035" class="ShowUserOutline"><img src="http://www.oschina.net/img/portrait.gif"></a>
  22. </td>
  23. <td class="body">
  24. <div class="r_title">
  25. %s楼:<b>%s</b>  发表于%s
  26. </div>
  27. <div class="r_content TextContent">%s</div>
  28. </td></tr>
  29. </table>
  30. </li>
  31. ]]
  32. --设置顶部内容.
  33. local comment_html = [[
  34. <div class="Comments" id="userComments">
  35. <h2>
  36. <a name="comments" href="#" class="more">回到顶部</a>
  37. <a href="#CommentForm" class="more" style="margin-right:10px;color:#ff3;">发表评论</a>
  38. 网友评论,共 %s条
  39. </h2>
  40. <ul>
  41. %s
  42. </ul>
  43. <ul class="pager">
  44. %s
  45. </ul>
  46. </div>
  47. ]]
  48. --设置循环li
  49. local page_li = [[
  50. <li class="page %s"><a href="?start=%s#comments">%s</a></li>
  51. ]]
  52. --输入参数 count start limit ,总数,开始,分页限制
  53. local function page(count,start,limit)
  54. --print(count,start,limit)
  55. local page = math.ceil(count/limit)
  56. local current_page = math.floor(start/limit) + 1
  57. --判断当前页面不超出分页范围.
  58. current_page = math.min(current_page,page)
  59. current_page = math.max(current_page,1)
  60. local is_first = ( current_page == 1 )
  61. local is_last = ( current_page == page )
  62. --打印页数,开始,结束.
  63. local page_offset = 3
  64. local start_page = math.max(current_page - page_offset ,1)
  65. local end_page = math.min(current_page + page_offset ,page)
  66. local page_html = ""
  67. if not is_first then
  68. page_html = page_html..[[<li class="page prev"><a href="?start=]]
  69. page_html = page_html..(current_page-2)*limit
  70. page_html = page_html..[[#comments"><</a></li>
  71. ]]
  72. end
  73. for i = start_page , end_page  do
  74. local tmp_current = ""
  75. if current_page == i then
  76. tmp_current = "current"
  77. end
  78. local tmp_div = string.format(page_li,tmp_current,(i-1)*limit,i)
  79. page_html = page_html..tmp_div
  80. end
  81. if not is_last then
  82. page_html = page_html..[[<li class="page next"><a href="?start=]]
  83. page_html = page_html..current_page*limit
  84. page_html = page_html..[[#comments">></a></li>
  85. ]]
  86. end
  87. return page_html
  88. end
  89. --接收参数。
  90. local uri = ngx.var.arg_uri
  91. --使用正则过滤url中的参数。
  92. local year,item_id = string.match(uri,"/blog/(%d+)/(%d+).html")
  93. local start = string.match(uri,"start=(%d+)") or "0"
  94. start = tonumber(start)--将字符串转换成数字。
  95. local limit = 10
  96. --拼接sql。
  97. local count_sql = " select count(*) as count from comment where item_id = "..item_id
  98. local count = query_mysql(count_sql)
  99. if count and #count > 0 then
  100. --对数据进行赋值.
  101. count  = count[1].count
  102. else
  103. count = "0"
  104. end
  105. count = tonumber(count)--将字符串转换成数字。
  106. local sql = " select id,uid,content,create_time from comment where item_id = "..item_id.." limit "..start..","..limit
  107. local res = query_mysql(sql)
  108. local comment_lis = ""
  109. for key,val in pairs(res) do
  110. local id = val["id"]
  111. local uid = val["uid"]
  112. local content = val["content"]
  113. local create_time = val["create_time"]
  114. --拼接字符串.
  115. comment_lis = comment_lis..string.format(comment_li,key,uid,create_time,content)
  116. end
  117. local page_lis = page(count,start,limit)
  118. local html = string.format(comment_html,count,comment_lis,page_lis)
  119. ngx.say(html)

代码将功能实现了。后续可以拆分成多个模块。其中生成分页部分比较复杂。

运行效果:使用了oschina的页面样式。

其中/blog/201311/127.html是静态html页面。

速度超级快。

3,nginx配置

参考:
http://wiki.nginx.org/HttpSsiModule
http://wiki.nginx.org/HttpCoreModule

  1. gzip  on;
  2. ssi on;
  3. root /data/comment;
  4. location /blog/list_comment {
  5. default_type 'text/html';
  6. content_by_lua_file '/data/comment/list_comment.lua';
  7. }
  8. location /blog/save_comment {
  9. default_type 'text/html';
  10. content_by_lua_file '/data/comment/save_comment.lua';
  11. }

在静态页面中增加ssi代码,这样就可以把uri当做参数传递了。
<!--# include virtual="/blog/list_comment?uri=$request_uri" -->

4,mysql修改打开文件数

因为开启了分区,所以读取文件数量肯定会多。
用ulimit -n查看打开文件数量。如果是1024,修改配置:

/etc/security/limits.conf 然后重启系统
* soft    noproc  65536
* hard    noproc  65536
* soft    nofile  65536
* hard    nofile  65536

然后修改my.conf配置文件:
vi /etc/my.cnf

[mysqld]
datadir=/var/lib/MySQL
socket=/var/lib/mysql/mysql.sock
user=mysql
symbolic-links=0
open_files_limit=65536

重启mysql生效,查看参数:
mysql> show variables like 'open%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 65536 |
+------------------+-------+
1 row in set (0.00 sec)

数据库表,按照设计成分区表。将数据分散。

  1. CREATE TABLE `comment` (
  2. `id` int(11) NOT NULL auto_increment COMMENT '主键',
  3. `item_id` int(11) NOT NULL COMMENT '评论项id',
  4. `uid` int(11) NOT NULL default '0' COMMENT '评论用户',
  5. `content` text NOT NULL COMMENT '内容',
  6. `create_time` datetime NOT NULL  COMMENT '创建时间',
  7. PRIMARY KEY  (`item_id`,`id`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8
  9. PARTITION BY HASH (`item_id`)
  10. PARTITIONS 1024;

插入测试数据:
insert into comment(`item_id`,content,create_time) values(127,CONCAT("conent test ",RAND()*1000),now());

源代码放到github上了。


https://github.com/luapkg/comment/

继续完善评论模块。

本文原文连接: http://blog.csdn.net/freewebsys/article/details/16944917 转载请注明出处!

来源:http://blog.csdn.net/freewebsys/article/details/16944917

【nginx+lua高性能web应用开发(二):开发评论模块(ssi+mysql)】相关推荐

  1. 构建高性能WEB站点笔记二

    构建高性能WEB站点笔记 因为是跳着看的,后面看到有提到啥epoll模型,那就补充下前面的知识. 第三章 服务器并发处理能力 3.2 CPU并发计算 进程 好处:cpu 时间的轮流使用.对CPU计算和 ...

  2. 使用nginx+lua实现web项目的灰度发布

    1.问题:小团队,快速迭代开发,版本发布没有经过测试就要放出去,怎样在内网测试过后在外网能在真实环境让内部人员再过一次测试且不影响外网用户 2.实现思想: a.至少要有两台机器 b.公司是统一出口IP ...

  3. nginx反代web页面没有正常显示_web漏洞-SSI注入漏洞深入详解

    SSI 注入全称Server-Side Includes Injection,即服务端包含注入.SSI 是类似于 CGI,用于动态页面的指令.SSI 注入允许远程在 Web 应用中注入脚本来执行代码. ...

  4. nutch开发(二)

    nutch开发(二) 文章目录 nutch开发(二) 开发环境 1.爬取后生成的目录结构 crawldb linkdb segments 2.阅读TestCrawlDbMerger createCra ...

  5. 用Nginx+Lua(OpenResty)开发高性能Web应用

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...

  6. 使用Nginx+Lua(OpenResty)开发高性能Web应用

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...

  7. 「京东开涛」使用Nginx+Lua(OpenResty)开发高性能Web应用

    几乎所有互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Ngi ...

  8. 服务器后端开发系列——《实战Nginx高性能Web服务器》

    1.高性能Web服务器Nginx的配置与部署研究(1)Nginx简介及入门示例 内容:概述Nginx的背景知识和简单的入门实例. 2.高性能Web服务器Nginx的配置与部署研究(2)Nginx入门级 ...

  9. 安装OpenResty(Nginx+Lua)开发环境

    首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作为一个Web Server使用.借助于Nginx的事件驱动模型 ...

最新文章

  1. 在Ubuntu 14.04 64bit上安装CHM阅读器KchmViewer 5.3
  2. Hibernate之Session解析
  3. Koa与Node.js开发实战(1)——Koa安装搭建(视频演示)
  4. ABAP中接收.NET语言byte[]类型返回值问题
  5. java抽象类到底能不能够实例化?
  6. KillTimer()的使用
  7. PHP表单提交参数验证类(可修改)
  8. jq画布插件_超炫HTML 5开发的jQuery进度条插件
  9. JS中[感叹号]function(){}()的理解
  10. ES5-3 循环、引用值初始、显示及隐式类型转换
  11. app inventor离线版_百度要哭了!今日头条出了搜索引擎了,还做了APP
  12. python核心编程笔记chapter 3
  13. 对系统组件化接口设计的一点看法
  14. 技术篇-HBase Coprocessor 的实现与应用
  15. MATLAB语言初步学习(五)
  16. 从零实现爬虫和情感分类模型(一)
  17. 纯css控制-表格表头固定,内容多时滚动内容
  18. 软考高项-信息系统项目管理师-精华笔记
  19. Google Office 战略 途经:收购JotSpot
  20. 谈论bringup我们到底在谈论什么?

热门文章

  1. 20位数字转化成6位不重复码_人力资源管理浅析身份证数字号码编排常识甄别年龄、性别、籍贯…...
  2. 如何使用Fiddler调试线上JS代码(转自:http://www.cnblogs.com/RockLi/p/3511132.html)
  3. 在Windows使用git工具将代码同步至github(作者:ying1989920)
  4. Mule web service调用中的复杂类型传递
  5. Linux 常见命令之Find \; +结合其它命令使用案例详解
  6. 打开高效文本编辑之门_Linux awk之关联数组
  7. Mysql数据目录初识
  8. 【Python-pywt】 小波变化库—Pywavelets 学习笔记
  9. oracle pi 3.14,Oracle中实现圆周率计算(一)
  10. [计算机视觉]人脸应用:人脸检测、人脸对比、五官检测、眨眼检测、活体检测、疲劳检测