OpenResty/Lua Practical Experience

2,698 views

Published on

1. Introduction to Lua and it's features
2. OpenResty: full-fledged web application server
3. Installation and "Hello World"
4. Nonblocking
5. Reconstruction of infov
6. Configuration skills
7. Table and JSON output problem
8. DNS and Hosts parser
9. More features

Published in: Technology
2 Comments
7 Likes
Statistics
Notes
No Downloads
Views
Total views
2,698
On SlideShare
0
From Embeds
0
Number of Embeds
420
Actions
Shares
0
Downloads
37
Comments
2
Likes
7
Embeds 0
No embeds

No notes for slide

OpenResty/Lua Practical Experience

  1. 1. OpenResty应用总结 技术部 - kim
  2. 2. 讲什么? • Lua 介绍 • Openresty 介绍 • 重构 Infov 的过程分享
  3. 3. 什么是 Lua? • 轻量级脚本语言 • 最小、最快、最简单 • 嵌入式
  4. 4. Lua 的特性 • Functional 函数式 • Table 数组、哈希表、集合、对象 • Closure 闭包 • Coroutine 协程
  5. 5. 著名的 Lua 项目 • 魔兽世界、愤怒的小鸟、Photoshop、仙剑 奇侠传五、淘宝内部 • 56.com (未来)
  6. 6. 什么是 OpenResty? • 最快的 Web 应用开发框架
  7. 7. • OpenResty (也称为 ngx_openresty)是一个全功能的 Web 应用服务器, 它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的 大多数依赖项。由章亦春于2011年底发表。 • OpenResty 通过汇聚各种设计精良的 Nginx 模块,从而将 Nginx 有效的 变成一个强大的 Web 应用服务器,这样,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种C以及Lua 模块,快速构造出足以胜任 10K+ 并发连接响应的超高性能Web 应用系统。 • OpenResty 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利 用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远 程后端诸如 MySQL,PostgreSQL,Memcached 以及 Redis 等都进行一 致的高性能响应。
  8. 8. 性能对比 • PHP-Fpm:速度慢、吞吐量低、短连接 • OpenResty:执行快、大吞吐量、连接池 • 春哥做的 benchmark: https://github.com/agentzh/mysql-driverbenchmark
  9. 9. 安装 • 下载解压: wget http://openresty.org/download/ngx_openresty-1.4.3.9.tar.gz tar -xzf ngx_openresty-1.4.3.9.tar.gz ./configure --help • 安装 mysql 连接开发包: yum install libdrizzle-devel • 安装: ./configure --prefix=/home/openresty/ --with-http_iconv_module --withhttp_postgres_module --with-http_drizzle_module --with-luajit --withpcre=/home/pcre-8.33 gmake && gmake install • 编辑 conf 配置 vi /home/openresty/nginx/conf/nginx.conf
  10. 10. Hello world - 1 location /helloworld { echo "hello world!"; }
  11. 11. Hello world - 2 location = /helloworld { content_by_lua ' ngx.say("hello world!") '; }
  12. 12. Hello world - 3 location = /helloworld { content_by_lua_file 'hello_world.lua'; } --hello_world.lua ngx.say("hello world!") ngx.flush(true)
  13. 13. 更复杂例子 # http://localhost/test?name=kim&class=A location /test { echo "uri = $uri"; echo "request_uri = $request_uri"; set_unescape_uri $name $arg_name; set_unescape_uri $class $arg_class; echo "name: $name"; echo "class: $class"; }
  14. 14. 无阻塞IO location /nonblocking { content_by_lua ' local res = ngx.location.capture("/query") if res.status == 200 then ngx.print(res.body) end'; }
  15. 15. 并发子请求 location = /nonblock-multi { content_by_lua ' local res1, res2, res3 = ngx.location.capture_multi{ {"/memc"}, {"/mysql"}, {"/postgres"} } ngx.say(res1.body, res2.body, res3.body) '; }
  16. 16. 重构 info.v.56.com
  17. 17. 为什么? • 前端核心接口 • PHP 性能瓶颈 • 缓存和数据库压力
  18. 18. 开发 • 公共模块:/lib • 实例代码:/lib/http.lua
  19. 19. 一般 debug 方法 • 直接抛出错误:error(“抛出个error!”) • assert(io.read("*number"), "invalid input") • Lua提供了错误处理函数pcall: r, msg = pcall(foo) • 还可以用 xpcall
  20. 20. 以上,我们一般不用。。。
  21. 21. 实际 debug 方法 • tailf /home/openresty/nginx/logs/error.log
  22. 22. 具体配置 • 新网段 + 3台新机器 • 高可用性:lvs + keepalive • 高可用 Cache:twemproxy + kt(12个) • 高性能:openresty • 实时性:缓存耦合(人气、评论),缓存更新 (直连 + httpsqs)
  23. 23. 切换原则 • 完全保留原PHP的所有读写功能,即线上功 能不受影响
  24. 24. Nginx配置技巧 • ~ 为区分大小写的匹配。 • ~* 不区分大小写的匹配。 • !~ 和 !~* 意为“不匹配的”。
  25. 25. 多重 if 判断 • # 仅当 uri 匹配 /?ids=xxxx ,即只读时才跳转至 lua: set $flag 0; if ($arg_ids ~* "(w)+") { set $flag "${flag}1"; } if ($request_uri !~ ".php") { set $flag "${flag}2"; } if ($arg_dy !~ "c") { set $flag "${flag}3"; } if ($flag = "0123") { content_by_lua_file 'vinfo.lua'; } fastcgi_pass 10.11.80.159:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; include fastcgi_params; expires off;
  26. 26. Infov当前的conf location ~ .php { fastcgi_pass unix:/home/php/php-fastcgi.sock; fastcgi_index index.php; include fastcgi_params; expires off; } location / { if ($request_uri ~* "luzhi") { rewrite ^/(.*)$ /index.php?$query_string last; } content_by_lua_file '/diska/htdocs/openresty/vinfo.lua'; } location /api { content_by_lua_file '/diska/htdocs/openresty/vapi.lua'; }
  27. 27. 切换过程 • 对每个应用,通过改 hosts 来灰度切换,有 问题立刻发现立刻修复 • 播放页和vxml 最后切换
  28. 28. 遇到的问题
  29. 29. Json输出问题 • PHP json_encode :会把 utf-8 强制 escape 成 unicode,除非是新版 php5.4 以上,可通 过指定 JSON_UNESCAPED_UNICODE 参数来 禁掉。 • Lua cjson :默认并不会对 utf-8 做 escape 处 理,输出的就是 utf-8
  30. 30. Table类型
  31. 31. lua 的 table 数据结构: typedef union TKey { struct { TValuefields; struct Node *next; /* for chaining */ } nk; TValue tvk; } TKey; typedef struct Node { TValue i_val; TKey i_key; } Node; typedef struct Table { CommonHeader; lu_byte flags; // 元表标记 lu_byte lsizenode; /* log2 of size of `node' array */ // 哈希部分大小 struct Table *metatable; // 元表 TValue *array; /* array part */ // 数组部分 Node *node; // 哈希部分 Node *lastfree; /* any free position is before this position */ // 第一个空闲位置指针 GCObject *gclist; int sizearray; /* size of `array' array */ // 数组部分大小 } Table;
  32. 32. • 数组部分:速度极快,内存比哈希省一半 • Hash部分:链状发散表,本身即无序(比 如用PHP接收到来自Lua的输出的时候,不 能简单地“认为”它是有序的!)
  33. 33. 文件vs模块 • 为什么要把配置文件写成模块 config.lua ?
  34. 34. 测试环境问题 • 测试环境和正式环境最好还是分开,特别 是不要在一个 server 配置里面
  35. 35. dns解析问题 • 可以通过安装和配置 nginx 本地 dns 服务来 添加 resolver,从而使 sock 能通过 Nginx core‘s dynamic resolver 来解析域名。 • 但是目前实际中还是直接使用 ip 来解析, 未来可以对 hosts 进行单独解析,这样就能 使用域名了。
  36. 36. Bug问题 • Error 级别的都是要尽量修复的 • Emerg 级别的是必须修复的 • 举例 gsub 引发的血案。。。
  37. 37. 入口不能太“窄” • vi /etc/sysctl.conf • net.netfilter.nf_conntrack_max = 655360 • net.netfilter.nf_conntrack_tcp_timeout_establ ished = 180
  38. 38. Timeout不能太短 • 无论是连接数据库、缓存还是Webservice, 超时时间太短反而不能充分发挥OpenResty 的优势
  39. 39. 现状与展望
  40. 40. 价值 • 1. 代码量 • 2. 开发效率 • 3. 性能提升
  41. 41. 站内应用 • • • • • • • 用户信息接口 短消息提醒接口 头部消息接口 视频观看记录接口 视频信息接口 专辑信息接口 等等中间层。。。
  42. 42. 缺少的 • 1. Session • 2. Http/Smtp/Rpc/… • 3. Html template • 等等。。。
  43. 43. 场景 • 数据层 • 缓存层
  44. 44. 资料 • 官网:http://openresty.org/ • nginx模块手册: https://github.com/chaoslawful/lua-nginxmodule • lua手册: http://www.lua.org/manual/5.2/manual.html
  45. 45. 谢谢!

×