SlideShare une entreprise Scribd logo
1  sur  76
OpenResty/Lua高级编程技巧
技术部 - kim
Debug
逻辑运算符 and、or 和 not 是经常隐藏 bug 的地方,比
如:
if (type(t) == 'table' and t.x == 'abc')
就算 t 不是 table 类型,那么 lua 的短路求值也不会对 t
进行求值,所以不会引发运行时错误
用 xpcall debug
function errorFunc()
local a = 20
print(a[10])
end
function errorHandle()
print(debug.traceback())
end
if xpcall(errorFunc,errorHandle) then
print("This is OK.")
else
print("This is error.")
end
ngx.now() :获取当前时间,包括毫秒数
os.clock() :返回CPU时间的描述,通常用于计算一段代
码的执行效率
os.data 日期对象函数:
print(os.date("%Y-%m-%d")) --输出2012-04-05
简单的写log函数(排重)
local logsUniquify = {} ——是的,这是个全局数组
function log(message, level)
if ngx and type(ngx.log) == 'function' then
local level = level or ngx.EMERG
if not logsUniquify[level .. message] then
ngx.log(level, message)
logsUniquify[level .. message] = true
end
end
return nil
end
以下的debug方式我们一般不用
1)直接抛出错误:error(“抛出个error!”)
2)assert(io.read("*number"), "invalid input")
3)Lua提供了错误处理函数pcall: r, msg = pcall(foo)
4)还可以用 xpcall
一般情况下我们是直接面对 error log 来开发 tailf
/home/openresty/nginx/logs/error.log
Safety
URL参数转义
urlencode : ngx.escape_uri
urldecode : ngx.unescape_uri
local act = ngx.var.arg_act and
ngx.unescape_uri(ngx.var.arg_act) or ngx.var.act
过滤/指定 remote_addr
ngx.var.remote_addr == "132.5.72.3"
获取用户ip
ClienIP = ngx.req.get_headers()["X-Real-IP"]
if ClientIP == nil then
ClientIP = ngx.req.get_headers()["x_forworded_for"]
end
if ClientIP == nil then
ClientIP = ngx.var.remote_addr
end
Sql Injection
local name = ngx.unescape_uri(ngx.var.arg_name)
local quoted_name = ngx.quote_sql_str(name)
local sql = "select * from users where name = " ..
quoted_name
htmlspecialchars的实现
function htmlspecialchars(str)
local rs = str or nil
if rs and type(rs) == 'string' then
rs = string.gsub(rs, '&', '&')
rs = string.gsub(rs, '"', '"')
rs = string.gsub(rs, "'", ''')
rs = string.gsub(rs, '<', '&lt;')
rs = string.gsub(rs, '>', '&gt;')
end
return rs
end
htmlentities 实现
过滤特殊字符
local illegal = {
["-"] = true, ["_"] = false, ["."] = false, ["!"] = true, [":"] = true, ["@"] = true,
["&"] = true, ["~"] = true, ["*"] = true, ["'"] = true, ['"'] = true, ["="] = false,
["("] = true, [")"] = true, ["["] = true, ["]"] = true, ["{"] = true, ["}"] = true,
["+"] = true, ["$"] = false, [","] = false, [";"] = true, ["?"] = true, ["%"] = true,
["^"] = true, ["/"] = true, ["|"] = true, ["#"] = true, ['-'] = true, ["_"] = false, ["。"] = true,
['!'] = true, [':'] = true, ['@'] = true, ['&'] = true, ['~'] = true, ['*'] = true, ['‘'] = true,
['’'] = true, ['“'] = true, ['”'] = true, ['('] = true, [')'] = true, ['['] = true, [']'] = true,
['{'] = true, ['}'] = true, ['+'] = true, ['¥'] = true, [','] = true, [';'] = true, ['?'] = true,
['%'] = true, ['^'] = true, ['/'] = true, ['……'] = true,
}
local filter = function(c)
if illegal[c] then
return ' '
end
return c
end
cnt = string.gsub(cnt, '([^a-zA-Z0-9])', filter)
Magics Convert
function escapeMagic(s)
local rs
if type(s) == 'string' then
rs = (s:gsub(‘[%-%.%+%[%]%(%)%$%^%%%?%*]',
'%%%1'):gsub('%z', '%%z'))
end
return rs
end
过滤 v 中的疑似网址特征
local spos = find(v, 'www') or find(v, '%.')
or find(v, '。') or find(v, '点')
local substring = ''
if spos then
substring = string.sub(s, spos, epos)
substring = g.escapeMagic(substring)
v = string.gsub(s, substring, '')
end
Build Queries
bind['so_refer_key'] = g.trim(vinfo['so_refer_key'])
bind['request_from'] = 'info_relate'
bind['wt'] = 'json'
bind['qt'] = 'standard'
bind['56_version'] = ngx.var.arg_rvc
bind['so_refer_key'] = ngx.var.arg_so_refer_key or ''
local param = neturl.buildQuery(bind)
local host = 'related_video.solr.56.com' --
local port = '49715'
local uri = '/solrRelateVideo/select?' .. param
if ngx.var.arg_dg == 'ml' then
print(uri)
end
xssfilter
— Filter the XSS attack
local xssfilter = require("lib.xssfilter")
local xss_filter = xssfilter.new()
data['title'] = g.htmlentities(xss_filter:filter(data['title']))
Sandbox
— 使用 closure 创建 sandbox (安全运行环境),比如为 io.open 提供权限控制的功能:
do
local oldOpen = io.open
local checkAccess = function (file, mode)
-- check if current user with 'mode' can access the 'file'
end
io.open = function (file, mode)
if checkAccess(file, mode) then
return oldOpen(file, mode)
else
return nil, "access, denied"
end
end
end
Table
Metatable
t = {}
print(getmetatable(t))
-- 输出为 nil,table 创建时默认没有元表
-- 任何 table 都可以作为任何值的元表,在Lua代码中,
只能设置table的元表
Table Sorting
t = {5,1,3,6,3,2}
t2 = table.sort(t, function(a1, a2)
return (a1 > a2) end) for i, v in pairs(t) do print(v)
end
unpack(1)
— 该函数将接收数组作为参数,并从下标1开始返回该数
组的所有元素:
string.find(unpack{"hello","ll"}) -- 等同于
string.find("hello","ll")
unpack(2)
— 经典应用 redis 的 hmget :
local tmpVids = {}
for i,v in ipairs(res) do
table.insert(tmpVids, tostring(v['video_id']))
end
local vextinfos = {}
local tbTimes = rds:hmget(rhkey, unpack(tmpVids))
unpack(3)
— redis 添加多个有序集元素的泛型调用:
rds:zadd(rzkey, unpack(zsetData))
Table Size(real)
function length(tbl)
local count = 0
if type(tbl) == 'table' then
for _ in pairs(tbl) do count = count + 1 end
end
return count
end
Table Flip
function array_flip(tbl)
local rs = tbl
if type(tbl) == 'table' then
rs = {}
for k,v in pairs(tbl) do
rs[v] = k
end
end
return rs
end
Random Pick
function array_rand(tbl, m)
local rs
if type(tbl) == 'table' and next(tbl) ~= nil then
rs = {}
local order = {}
local n = #tbl
for i = 1, n do
order[i] = {rnd = math.random(), idx = i}
end
table.sort(order, function(a,b) return a.rnd < b.rnd end)
for i = 1, m do
if order[i] then rs[i] = order[i].idx end
end
end
return rs
end
Intersect by Key
function array_intersect_key(t1, t2)
local rs = t1
if type(t1) == 'table' and type(t2) == 'table' then
rs = {}
for k,v in pairs(t1) do
if t2[k] ~= nil then rs[k] = v end
end
end
return rs
end
Deep Compare
function deepcompare(t1, t2)
local ty1 = type(t1)
local ty2 = type(t2)
if ty1 ~= ty2 then return false end
-- non-table types can be directly compared
if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
-- as well as tables which have the metamethod __eq
for k1,v1 in pairs(t1) do
local v2 = t2[k1]
if v2 == nil or not deepcompare(v1,v2) then return false end
end
for k2,v2 in pairs(t2) do
local v1 = t1[k2]
if v1 == nil or not deepcompare(v1,v2) then return false end
end
return true
end
模块初始化与 __index
— 定义模块实例化的方法:
--[[ init module ]]
module(...)
_VERSION = '1.0.0'
--[[ indexed by current module env. ]]
local mt = {__index = _M};
--[[
instantiation
@return table
]]
function new(self)
return setmetatable({}, mt);
end
Default Value
function setDefault(table, default)
local mt = {__index = function() return default end }
setmetatable(table,mt)
end
tab = {x = 10, y = 20}
setDefault(tab,0)
print(tab.x,tab.z) --10 0
Write Prohibited
setmetatable(_M, {
__newindex = function (table, key, val)
ngx.log(ngx.EMERG, 'attempt to write to undeclared variable "' ..
key .. '" in ' .. table._NAME);
end
})
_M.unexists = "hello" -- 报错:’attempt to write to undeclared variable
"unexists" in $module'
Table Traversal
for k,v in g.pairsByKeys(idDel) do
print(k .. ':' .. v .. "n")
end
function pairsByKeys(tb, f)
local a = {}
for n in pairs(tb) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function() -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], tb[a[i]]
end
end
return iter
end
Sort by Value
function sortAssoc(tb, order, limit)
local rs = nil
if type(tb) == 'table' then
rs = {}
local tmp = {}
for k,v in pairs(tb) do
table.insert(tmp, {key = k, val = tonumber(v)})
end
if next(tmp) ~= nil then
if order and order == 'DESC' then
table.sort(tmp, function(a, b) return b.val < a.val end)
else
table.sort(tmp, function(a, b) return b.val > a.val end)
end
end
for i,v in ipairs(tmp) do
table.insert(rs, {v['key'], v['val']})
if limit and (i >= limit) then break end
end
end
return rs
end
Multi-Array Sorting
local data = {
{id=3, data=421}, {id=23, data=321}, {id=3, data=422}, {id=5, data=321},
{id=1, data=4214}, {id=3, data=44}
}
table.sort(data, function(a, b)
if a['id'] < b['id'] then
return true
elseif a['id'] == b['id'] then
if a['data'] < b['data'] then
return true
else
return false
end
else
return false
end
end)
Metatable Prohibited
mt = {}
mt.__metatable = "can not read/write"
setmetatable(s1, mt)
print(getmetatable(s1)) -- "cannot read/write"
setmetatable(s1, {}) -- cannot change protected metatable
Metamethod
Lua中提供的元表是用于帮助 Lua 数据变量完成某些非预
定义功能的个性化行为,如两个table的相加。
假设a和b都是table,通过元表可以定义如何计算表达式
a+b。
当Lua试图将两个table相加时,它会先检查两者之一是否
有元表,然后检查该元表中是否存在__add字段,如果有
,就调用该字段对应的值。
这个值就是所谓的“元方法”,这个函数用于计算table的和
。
Function
Essence
Lua 将所有独立的程序块视为一个匿名函数的函数体,并
且该匿名函数还具有可变长实参
Returning Values
1. 模块、函数 可以考虑 “有效值|nil,错误信息” 这样的双
值返回,resty 中的大部分模块都是这样写的
2. function 尽量返回单值,特别是业务逻辑的函数,多值
返回虽然是 lua 的特色,但是不利于移植
3. 空值或者无效值尽量用 nil 来表示,而不要用 空table
、''、0、false 等等来表示,只有 nil 才是真正意义上的“
无效值”
Proper Tail Calls
在Lua中支持这样一种函数调用的优化,即不耗费任何栈
空间的“尾调用消除”。我们可以将这种函数调用方式视为
goto语句,如:
function f(x) return g(x) end
形参 vs 实参
1. 实参多于形参,多出的部分被忽略
2. 形参多于实参,没被初始化的形参的缺省值为nil
function foo(a, b, c)
print(a, b, c)
end
foo('a', 'b', 'c', 'd') -- 'd' 被忽略
foo('a') -- 这时形参 b 和 c 都是 nil
Performace
Local Sharings
http {
lua_shared_dict lcache 64m;
...
}
dict.lua 模块介绍
http://wiki.nginx.org/HttpLuaModule#ngx.shared.DICT
Fastest Trim
function trim(s)
if type(s) == 'string' then
local match = string.match
return match(s,'^()%s*$') and '' or match(s,'^%s*(.*%S)')
end
return s
end
Memcached
1. https://github.com/agentzh/lua-resty-memcached
2. 自封装 memd.lua 模块介绍
Mysql
1. https://github.com/agentzh/lua-resty-mysql
2. 自封装 mysql.lua 模块介绍
Redis
https://github.com/agentzh/lua-resty-redis
自封装 redis.lua 模块介绍:
1)让 lua-resty-redis 的返回值变得规范
2)lazy connecting
3)添加 debug 功能和 log 功能
4)实现一些特殊的功能,比如 hclear
5)close 方法默认设置 set_keepalive
Block
不需要在程序起始处声明所有局部(local)变量,在需
要的时候才声明变量其实是好习惯,缩短变量的作用域
在任何时候都是好的。
List
list = nil
for v in values do
list = {next = list, value = v}
end
local l = list
while l do
print(l.value)
l = l.next
end
跳转实例
=== TEST 13: rewrite args (not break cycle by default)
--- config
location /bar {
echo "bar: $uri?$args";
}
location /foo {
#set $args 'hello';
rewrite_by_lua '
ngx.req.set_uri_args("hello")
ngx.req.set_uri("/bar", true)
';
echo "foo: $uri?$args";
}
--- request
GET /foo?world
--- response_body
bar: /bar?hello
How to “continue”?
local bContinue
for k, v in pairs(tbl) do
bContinue = false
......
if not bContinue then
......
if needToContinue then
bContinue = true
end
end
if not bContinue then
-- continue to do things
end
end
elseif vs else if
if ... then
else
if ... then
end
end
if ... then
elseif ... then
end
“select”
count = select(2, string.gsub(str," "," "))
-- string.gsub 第二个返回值是空格替换次数,select则选
择该返回值,即 str 中空格的数量
文件/IO
1. io.write("hello","world") --写出的内容为helloworld
2. io.read("*all")会读取当前输入文件的所有内容
3. io.read(0)是一种特殊的情况,用于检查是否到达了文
件的末尾。如果没有到达,返回空字符串,否则nil
Serialize
function serialize(o)
if type(o) == "number" then
io.write(o)
elseif type(o) == "string" then
--string.format函数的"%q"参数可以转义字符串中的元字符。
io.write(string.format("%q",o))
elseif type(o) == "table" then
io.write("{n")
--迭代table中的各个元素,同时递归的写出各个字段的value。
--由此可以看出,这个简单例子可以支持嵌套的table。
for k,v in pairs(o) do
--这样做是为了防止k中包含非法的Lua标识符。
io.write(" ["); serialize(k); io.write("] = ")
serialize(v)
io.write(",n")
end
io.write("}n")
else
error("cannot serialize a " .. type(o))
end
end
Size and Seek
1. local f = assert(io.open(filename,"r"))
2. local current = f:seek() --获取当前位置
3. local size = f:seek("end") --获取文件大小
4. f:seek("set",current) --恢复原有的当前位置
读取文件优化
下面是Shell中wc命令的一个简单实现:
local BUFSIZE = 8192
local f = io.input(arg[1]) --打开输入文件
local cc, lc, wc, = 0, 0, 0 --分别计数字符、行和单词
while true do
local lines,rest = f:read(BUFSIZE,"*line")
if not lines then
break
end
if rest then
lines = lines .. rest .. "n"
end
cc = cc + #lines
--计算单词数量
local _, t = string.gsub(lines."%S+","")
wc = wc + t
--计算行数
_,t = string.gsub(line,"n","n")
lc = lc + t
end
print(lc,wc,cc)
Socket
Socket Connect
-- 用 ngx.socket.tcp 才能百分百支持 nonblocking
local sock = ngx.socket.tcp()
sock:settimeout(1000) -- one second
local ok, err = sock:connect("127.0.0.1", 11211)
local bytes, err = sock:send("flush_allrn")
if not bytes then
ngx.say("failed to send query: ", err)
return
end
local line, err = sock:receive()
if not line then
ngx.say("failed to receive a line: ", err)
return
end
ngx.say("result: ", line)
local ok, err = sock:setkeepalive(60000, 500)
if not ok then
ngx.say("failed to put the connection into pool with pool capacity 500 "
.. "and maximal idle time 60 sec")
return
end
Settimeout
sock:settimeout(1000)
ok, err = tcpsock:connect(host, port, options_table?)
sock:settimeout(1000)
bytes, err = tcpsock:send(data)
sock:settimeout(1000)
data, err, partial = tcpsock:receive(size) —读timeout是不会close掉连接的
local reader = sock:receiveuntil("rn--abcedhb")
sock:settimeout(1000)
while true do
……
end
ok, err = tcpsock:close()
Coroutine
协程示例
协程的经典示例:“生产者-消费者”问题:
--消费者
function receive()
local status, value = coroutine.resume(producer) --消费
return value
end
--生产者
function send(x)
coroutine.yield(x) --挂起
end
--协程
producer = coroutine.create(
function()
while true do
local x = io.read() --产生新值
send(x)
end
end)
cosocket 读取大数据
local sock, err = ngx.req.socket()
if not sock then
ngx.say("failed to get request socket: ", err)
return
end
sock:settimeout(10000) -- 10 sec timeout
while true do
local chunk, err = sock:receive(4096)
if not chunk then
if err == "closed" then
break
end
ngx.say("faile to read: ", err)
return
end
process_chunk(chunk)
end
Some Modules
Serialize Module
—- 使用 serialize 模块的函数对 PHP序列化的字符串进行反序列化,或者对lua
的 table 进行PHP序列化
require("lib.serialize")
local srlz = serialize
local unsrlz = unserialize
local luatable = unsrlz(php_serialized_string)
local php_serialized_string = serialize(luatable)
luarocks
查看 luajit 版本:
ls /home/openresty/luajit/bin/luajit-2.0.2
wget http://luarocks.org/releases/luarocks-2.0.13.tar.gz
tar -xzvf luarocks-2.0.13.tar.gz
cd luarocks-2.0.13/
./configure --prefix=/usr/local/openresty/luajit 
--with-lua=/usr/local/openresty/luajit/ 
--lua-suffix=jit-2.0.2 
--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.0/
make build
sudo make install
PS:--lua-suffix 就是上面 luajit 的后缀
lua-snappy
1. 从 https://github.com/forhappy/lua-snappy 下载并解压。
2. CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/home/openresty/luajit/include/luajit-2.0
export CPLUS_INCLUDE_PATH
3. 进入 lua-snappy-master 里面:
cd /lua-snappy-master ./sysconfig
vi Makefile
4. 加上 luajit 路径并加入到编译命令中:
CPPFLAGS=-fPIC -shared -Wall -g -O2 -I/home/openresty/luajit/include/luajit-2.0/
$(CC) $(CPPFLAGS) -o $@ -c $^
5. 编译安装:
make
6. 把 so 放到 lib 里面: cp snappy.so /home/openresty/lualib/
模板技术
https://github.com/bungle/lua-resty-template
FAQ

Contenu connexe

Tendances

Node.JS
Node.JSNode.JS
Node.JS
eibaan
 
Java осень 2012 лекция 6
Java осень 2012 лекция 6Java осень 2012 лекция 6
Java осень 2012 лекция 6
Technopark
 
Java Thread Cronometro
Java Thread CronometroJava Thread Cronometro
Java Thread Cronometro
jubacalo
 

Tendances (19)

Collection pipeline par Mathieu Godart
Collection pipeline par  Mathieu GodartCollection pipeline par  Mathieu Godart
Collection pipeline par Mathieu Godart
 
Modern Mobile Web Apps
Modern Mobile Web AppsModern Mobile Web Apps
Modern Mobile Web Apps
 
Node.JS
Node.JSNode.JS
Node.JS
 
Anatomy of the loadable kernel module (lkm)
Anatomy of the loadable kernel module (lkm)Anatomy of the loadable kernel module (lkm)
Anatomy of the loadable kernel module (lkm)
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco
 
Menguak Misteri Module Bundler
Menguak Misteri Module BundlerMenguak Misteri Module Bundler
Menguak Misteri Module Bundler
 
D2D Pizza JS Игорь Ковган "Koa поможет"
D2D Pizza JS Игорь Ковган "Koa поможет"D2D Pizza JS Игорь Ковган "Koa поможет"
D2D Pizza JS Игорь Ковган "Koa поможет"
 
The Flavor of TypeScript
The Flavor of TypeScriptThe Flavor of TypeScript
The Flavor of TypeScript
 
Rambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тестыRambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тесты
 
BABELで、ES2015(ES6)を学ぼう!
BABELで、ES2015(ES6)を学ぼう!BABELで、ES2015(ES6)を学ぼう!
BABELで、ES2015(ES6)を学ぼう!
 
Testování prakticky
Testování praktickyTestování prakticky
Testování prakticky
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im Produktivbetrieb
 
C++14 reflections
C++14 reflections C++14 reflections
C++14 reflections
 
Java осень 2012 лекция 6
Java осень 2012 лекция 6Java осень 2012 лекция 6
Java осень 2012 лекция 6
 
Mikstura it2013
Mikstura it2013Mikstura it2013
Mikstura it2013
 
Java Thread Cronometro
Java Thread CronometroJava Thread Cronometro
Java Thread Cronometro
 
JUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationJUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentation
 

En vedette

lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
hugo
 
What's Hot On Facebook - 20/07/2011
What's Hot On Facebook - 20/07/2011What's Hot On Facebook - 20/07/2011
What's Hot On Facebook - 20/07/2011
David Nattriss
 
мифы и легенды грузия
мифы и легенды грузиямифы и легенды грузия
мифы и легенды грузия
Maia Odisharia
 
FLIBS 2008 Presentation / FTZ &amp; Yacht Importations
FLIBS 2008 Presentation / FTZ &amp; Yacht ImportationsFLIBS 2008 Presentation / FTZ &amp; Yacht Importations
FLIBS 2008 Presentation / FTZ &amp; Yacht Importations
mterorotua
 
Présentation Manacoach
Présentation ManacoachPrésentation Manacoach
Présentation Manacoach
Manacoach
 
Ireland the road to partition guzman 2011
Ireland the road to partition guzman 2011Ireland the road to partition guzman 2011
Ireland the road to partition guzman 2011
Patricia Guzman
 
PVC Membrane Roofing Technology 250708 (3)
PVC Membrane Roofing Technology 250708 (3)PVC Membrane Roofing Technology 250708 (3)
PVC Membrane Roofing Technology 250708 (3)
ARIJIT BASU
 

En vedette (20)

基于OpenResty的百万级长连接推送
基于OpenResty的百万级长连接推送基于OpenResty的百万级长连接推送
基于OpenResty的百万级长连接推送
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
 
OpenResty/Lua Practical Experience
OpenResty/Lua Practical ExperienceOpenResty/Lua Practical Experience
OpenResty/Lua Practical Experience
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
 
What's Hot On Facebook - 20/07/2011
What's Hot On Facebook - 20/07/2011What's Hot On Facebook - 20/07/2011
What's Hot On Facebook - 20/07/2011
 
Teach
TeachTeach
Teach
 
LIFE - 4/7/2010 - Lavender Recipes
LIFE - 4/7/2010 - Lavender RecipesLIFE - 4/7/2010 - Lavender Recipes
LIFE - 4/7/2010 - Lavender Recipes
 
Cordoba 107 bahia de rosas algarrobo
Cordoba 107 bahia de rosas algarroboCordoba 107 bahia de rosas algarrobo
Cordoba 107 bahia de rosas algarrobo
 
Ownuse
OwnuseOwnuse
Ownuse
 
мифы и легенды грузия
мифы и легенды грузиямифы и легенды грузия
мифы и легенды грузия
 
Retratos Artísticos por Sheila Santos
Retratos Artísticos por Sheila SantosRetratos Artísticos por Sheila Santos
Retratos Artísticos por Sheila Santos
 
FLIBS 2008 Presentation / FTZ &amp; Yacht Importations
FLIBS 2008 Presentation / FTZ &amp; Yacht ImportationsFLIBS 2008 Presentation / FTZ &amp; Yacht Importations
FLIBS 2008 Presentation / FTZ &amp; Yacht Importations
 
Tudósok akik hittek a hatnapos teremtésben - frissítve
Tudósok akik hittek a hatnapos teremtésben - frissítveTudósok akik hittek a hatnapos teremtésben - frissítve
Tudósok akik hittek a hatnapos teremtésben - frissítve
 
Présentation Manacoach
Présentation ManacoachPrésentation Manacoach
Présentation Manacoach
 
Ireland the road to partition guzman 2011
Ireland the road to partition guzman 2011Ireland the road to partition guzman 2011
Ireland the road to partition guzman 2011
 
Search Engines
Search EnginesSearch Engines
Search Engines
 
Bellido Cert Ificates Awards
Bellido  Cert Ificates AwardsBellido  Cert Ificates Awards
Bellido Cert Ificates Awards
 
Ryan E. Crumley
Ryan E. CrumleyRyan E. Crumley
Ryan E. Crumley
 
PVC Membrane Roofing Technology 250708 (3)
PVC Membrane Roofing Technology 250708 (3)PVC Membrane Roofing Technology 250708 (3)
PVC Membrane Roofing Technology 250708 (3)
 
EPM assignment 2
EPM assignment 2EPM assignment 2
EPM assignment 2
 

Plus de Ho Kim

Plus de Ho Kim (14)

解决Lvs上行丢包的过程和收获
解决Lvs上行丢包的过程和收获解决Lvs上行丢包的过程和收获
解决Lvs上行丢包的过程和收获
 
40 Powerful Shortcuts of Xcode 6.x
40 Powerful Shortcuts of Xcode 6.x40 Powerful Shortcuts of Xcode 6.x
40 Powerful Shortcuts of Xcode 6.x
 
Project Management Using Redmine
Project Management Using RedmineProject Management Using Redmine
Project Management Using Redmine
 
Web Caching Architecture and Design
Web Caching Architecture and DesignWeb Caching Architecture and Design
Web Caching Architecture and Design
 
Lua 30+ Programming Skills and 20+ Optimization Tips
Lua 30+ Programming Skills and 20+ Optimization TipsLua 30+ Programming Skills and 20+ Optimization Tips
Lua 30+ Programming Skills and 20+ Optimization Tips
 
人人-56 账号拆分项目总结
人人-56 账号拆分项目总结人人-56 账号拆分项目总结
人人-56 账号拆分项目总结
 
JavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization SkillsJavaScript 80+ Programming and Optimization Skills
JavaScript 80+ Programming and Optimization Skills
 
Character Encoding and Database Transcoding Project
Character Encoding and Database Transcoding ProjectCharacter Encoding and Database Transcoding Project
Character Encoding and Database Transcoding Project
 
Video Upload Architecture of 56.com
Video Upload Architecture of 56.comVideo Upload Architecture of 56.com
Video Upload Architecture of 56.com
 
PHP Optimization for Millions Visits Level
PHP Optimization for Millions Visits LevelPHP Optimization for Millions Visits Level
PHP Optimization for Millions Visits Level
 
Comment System of 56.com
Comment System of 56.comComment System of 56.com
Comment System of 56.com
 
Git Essence Tutorial
Git Essence TutorialGit Essence Tutorial
Git Essence Tutorial
 
MongoDB Basics and Tutorial
MongoDB Basics and TutorialMongoDB Basics and Tutorial
MongoDB Basics and Tutorial
 
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming Skills
 

OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips