技术开发阅读笔记
Metrics 指标设计之 RED 大法
- Rate 速率
- Errors 错误
- Duration 持续时间
Metrics指标设计之USE大法
- Utilization 利用率
- Saturation 饱和状态
- Errors 事件错误
OpenResty系统调优
- CPU affinity 亲和性配置
- NGINX 配置优化
- Linux sysclt 设置
- Intel Quickassist
NGINX 指令配置
- keepalive_timeout, keepalive_requests
- sendfile on - copy fd at kernel level
- tcp_nopush, tcp_nodelay
- listen backlog reuserport
Linux sysclt 设置
- Memory
- Size of processor queue
- Maximum TCP buffer size
- Disable TCP timestamps
OpenResty / Lua 高级编程技巧,OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips
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
以下的 debug 方式我们一般不用
- 直接抛出错误:error(抛出个 error!)
- assert(io.read("*number"), "invalid input")
- Lua提供了错误处理函数 pcall:r, msg = pcall(foo)
- 还可以用 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
local clienIP = ngx.req.get_headers()["x-real-ip"] if clienIP == nil then clienIP = ngx.req.get_headers()["x_forworded_for"] end if clienIP == nil then clienIP = 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, '<', '<') rs = string.gsub(rs, '>', '>') end return rs end
过滤特殊字符
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
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 ipairs(t) do print(v) end
在线代码运行环境
缓存雪崩、缓存击穿、缓存穿透
缓存雪崩
大量的 KEY 过期时间过于集中,导致瞬时很多缓存失效,由此可能导致数据库压力陡然升高。
解决方案:将失效时间随机打乱,如在系统启动预热时设定一定程度上离散的过期时间。
缓存击穿
缓存中某一个 KEY 过期失效,如果此时有大量请求过来无法命中缓存的 KEY,缓存层像被凿开了一个口子一样流入大量数据库查询请求
解决方案:双重校验方式从数据库中读取数据到缓存。双重校验:第一层查询缓存失败后,进入临界区,保证同时只有一个请求线程读取数据库,进入临界区后再次尝试缓存,仍然没有命中则查询数据库。
缓存穿透
外部请求不断查询一个系统中不存在的数据,服务无法命中缓存转而每次尝试从数据库中查询。
解决方案:对查询结果为空 key 设置值为 null 的缓存,牺牲缓存空间换响应时间。把所有非法的key映射到一个bitmap中,通过bitmap拦截。《布隆过滤器》原理
JAVA 基本类型 int 和 long 的理解
long 可以用来计算光在一定时间内走过的距离。
光在一秒内大约传播 30 万千米。如果编写一个程序来跟踪光走过的距离,那么7秒后 int 类型就超出范围类,而 long 类型能够计算大约 975 年。不相信吗?可以看看这个gist中的计算。
Light Distance Calculation: 32-bit vs. 64-bit
Some Facts:
- Maximum Positive Signed 32-bit Integer:
(2^31) - 1 = 2,147,483,647
- Maximum Positive Signed 64-bit Integer:
(2^63) - 1 = 9,223,372,036,854,775,807
- Speed of Light:
299,792,458 m/s
If an integer were tracking meters in real time:
- 32-bit Calculation
In seconds:2,147,483,638 m / 299,792,458 m/s = 7.16323436662 s
- 64-bit Calculation
In seconds:9,223,372,036,854,775,807 m / 299,792,458 m/s = 30,765,857,481.5 s
In minutes:30,765,857,481.5 s / 60 s/min = 512,764,291.358 mins
In hours:512,764,291.358 mins / 60 mins/hour = 8,546,071.52264 hours
In days:8,546,071.52264 hours / 24 hours/day = 356,086.313443 days
In years:356,086.313443 days / 365.25 days/year = 974.911193547 years
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论