OpenResty高性能亿万级商品详情页
1.课程介绍--
2.openresty介绍
官网:https://openresty.org/cn/
openresty的目标是让你的Web服务直接跑在Nginx服务内部,充分利用Nginx的非阻塞I/O模型,不仅仅对HTTP客户端请求,甚至对远程后端诸如MySQL,PostgreSQL,Memcached以及Redis等都进行一致的高性能响应。
3.openresty常用架构
负载均衡:
LVS+HAProxy将流量转发给核心Nginx1和核心Nginx2,即实现了流量的负载均衡
单机闭环:
所有想要的数据都能从本服务器直接获取,在大多数时候无需通过网络去其他服务器获取
分布式闭环:
单机闭环会遇到如下两个主要问题:
1.数据不一致(比如没有采用主从架构导致不同服务器数据不一致)
2.遇到存储瓶颈(磁盘或者内存遇到了天花板)。
解决数据不一致的比较好的办法是采用主从或者分布式集中存储;而遇到存储瓶颈就需要进行按照业务键进行分片,将数据分散到多台服务器。
接入网关:
接入网关也可以叫做接入层,即接收到流量多入口,在入口我们进行如下事情
4.openresty下载与安装
windows安装:直接解压安装,启动时,只需要执行nignx.exe
linux安装centOS6.5
1.解压:tar -xzvf openresty-VERSION.tar.gz
2.配置:进入openresty-VERSION/目录,然后输入以下命令配置
./configure
默认—prefix=/usr/local/openresty程序会被安装到/usr/local/openresty目录。
3.安装
make&&make install
注意:openresty依赖库有:perl5.6.1+,libreadline,libpcre,libssl。所以我们需要先安装好这些依赖库
yum install redline-devel pure-devel openssl-level perl gcc
4.验证:
关闭防火墙,访问http://外网IP
5.lua介绍与下载安装
lua语法介绍
lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。官网:http://www.lua.org/
1.CentOS下安装lua
tar zxf lua-5.3.4.tar.gz
cd lua-5.3.4
make linux test
make install
查看lua版本:lua -v
6.lua语法-数据类型与变量定义
2.helloworld
1.交互模式,输入lua
2.脚本式,创建一个以lua结尾的文件,例如hello.lua文件内容print(“hello world”)
3.lua数据类型与变量
lua中有8个基本类型分别为:nil,boolean,number,string,userdata,function,thread和table
数据类型 描述
nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)
boolean 包含两个值:false和true
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由C或Lua编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua中的表(table)其实是一个“关联数组”(associative arrays),数组的索引可以是数字或者字符串。在Lua里,table的创建是通过“构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。
Lua变量有三种类型:全局变量,局部变量,表中的域
Lua中变量全是全局变量,那怕是语句块或是函数里,除非用local显式声明为局部变量。
局部变量的作用域为从声明位置开始到所在语句块结束。
变量的默认值均为nil。
--单行注释
--[[
多行注释
--]]
7.lua语法-运算符
1.赋值运算符
—赋值str=“hello”..”world” —..lua中的字符连接
a,b=10,20 —a=10,b=20
c,d,e=1,2
2.算术运算符
下表列出了lua语言中的常用算术运算符,设定A的值为10,B的值为20:
+ 加法
- 减法
* 乘法
/ 除法
% 取余
^ 乘幂
- 负号
3.关系运算符
下表列出了lua语言中的常用关系运算符,设定A的值为10,B的值为20:
操作符 描述
== 等于
~= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
4.逻辑运算符
and 逻辑与操作符,若A为false,则返回A,否则返回B。
or 逻辑或操作符,若A为true,则返回A,否则返回B。
not 逻辑非操作符,与逻辑运算结果相反,如果条件为true,逻辑非为false。
5.其它运算符
.. 连接两个字符串
# 一元运算符,返回字符串或表的长度
str=“helloworld”
print(#str) —得到10
8.lua语法-流程控制
1.条件
2.循环
--while循环
a=10
while(a>0)
do
print(a)
a = a -1
end
--repeat until:重复执行循环,直到指定的条件为真时为止
b=10
repeat
print(b)
b=b-1
until(b<1)
--for循环
for a=1,10,1 do
print(a)
end
9.lua语法-数组与泛型for
— 数组大小不固定,下标是从1开始。
arr={“aaa”,”bbb”,”ccc”}
for index=1,#arr do
print(arr[index])
end
—泛型for
for i,v in impairs(arr) do
print(i,v)
end
10.lua语法-函数介绍
—函数
function fun(a,b,c)
return a,b,c
end
value1,value2,value3 = fun(1,2,3,4,5)
print(value1,value2,value3)
11.lua语法-table与模块,包介绍
mytable={} —声明一个table
mytable.first=“tom”
mytable.second=“james”
print(mytable[1])
print(mytable.first)
print(mytable[“second”])
模块类似于一个封装库,从5.1开始,Lua加入了标准的模块管理机制
module={}
module.index=1
function module.sum(a,b)
return a+b
end
—引入模块
require “module”
print(module.index)
print(module.sum(10,20))
12.openresty快速入门
1.helloworld
openresty1.9.3.1及以下版本,请使用content_by_lua命令:在openresty1.9.3.2以上,content_by_lua改成了content_by_lua_block.可使用nginx -V命令查看版本号
location / {
#root html;
#index index.html index.htm;
default_type text/html;
content_by_lua_block{
ngx.say(“hello world”);
}
}
我们也可以使用content_by_lua_file来引入一个lua文件
location /{
#root html;
#index index.html index.htm;
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/conf/my.lua;
}
13.openresty获取http请求信息
1.获取uri参数
获取一个uri有两个方法:ngx.req.get_uri_args,ngx.req.get_post_args,二者主要的区别是参数来源有区别
--获取get请求参数
local arg=ngx.req.get_uri_args()
for k,v in pairs(arg) do
ngx.say(“[GET] key:”,k,” v:”,v)
ngx.say(“换行符”)
end
—获取post请求时,请求参数
ngx.req.read_body() —解析body参数之前一定要先读取body
local arg = ngx.req.get_post_args()
for k,v in pairs(args) do
ngx.say(“[POST] key:”,k,” v:”,v)
ngx.say(“<br>”)
end
2.获取header
—获取header
local headers = ngx.req.get_headers()
for k,v in pairs(headers) do
ngx.say(“[header] name;”,k,” v:”,v)
ngx.say(“<br>”)
end
3.获取body
--获取body信息
local data =ngx.req.get_body_data()
ngx.say(data)
ngx.req.get_body_data()请求体,会偶尔出现读取不到直接返回nil的情况。如果请求体尚未被读取,请先调用ngx.req.read_body(或打开lua_need_request_body选项强制本模块读取请求体,词方法不推荐)
14.openresty操作redis
—连接redis
github上的redis连接代码只是一个示例代码,生产环境并发量过大,可能会崩溃的。
生产环境redis连接代码:http://wiki.jikexueyuan.com/project/openresty/redis/out_package.html
15.商品详情页方案介绍
image.png
16.twemproxy+redis环境搭建介绍
Twemproxy是一个Twitter开发的一个redis代理proxy,Twemproxy通过引入一个代理层,可以将其后端的多台Redis或Memcached实例进行统一管理与分配,使应用程序只需在Twemproxy上进行操作,而不用关心后面具体有多少个真实的Redis或Memcached存储,简单的说,就是有了Twemproxy,客户端不直接访问Redis服务器,而是通过twemproxy间接访问。
Twenproxy特性:
1.支持失败节点自动删除
2.支持设置HashTag
3.减少与redis的直接连接数
4.自动分片到后端多个redis实例上
5.避免单点问题
6.支持状态监控
7.使用pipeline处理请求和响应
8.并不是支持所有redis命令
示例:
示例中使用一个twemproxy+两台redis(未做主从)
实际部署中需要使用keepalived解决twemproxy单点问题,并且需要做redis主从
192.168.93.134 twemproxy
192.168.93.133 redis
192.168.93.132 redis
192.168.93.134操作
1.安装autoconf
wget [http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz](http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz)
tar -zxvf autoconf-2.69.tar.gz
cd autoconf-2.69
./configure && make && make install
2.安装automake
wget [http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz](http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz)
tar -zxvf automake-1.15.tar.gz
cd automake-1.15
3.安装libtool
wget [https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz] (https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz)
tar -zxvf lib tool-2.4.6.tar.gz
cd lib tool-2.4.6
./configure && make && make install
4.安装twemproxy
wget [https://github.com/twitter/twemproxy/archive/master.zip](https://github.com/twitter/twemproxy/archive/master.zip)
unzip master
cd twemproxy-master
aclocal
autoreconf -f -i -Wall,no-obsolete
mkdir /usr/local/twemproxy
./configure --prefix=/usr/local/twemproxy/
make && make install
5.配置twemproxy
将twemproxy-master下的conf目录复制到/usr/local/twemproxy下
cp -r ./conf/usr/local/twemproxy/
cd /usr/local/twemproxy
修改conf目录下nutcracker.yml文件内容
alpha:
listen:192.168.93.134:22121
hash:fnv1a_64
distribution:ketama
atuo_eject_hosts:true
redis:true
server_retry_timeout:2000
server_failure_limit:1
servers:
-192.168.93.133:6379:1
-192.168.93.134:6379:1
启动twemproxy
注意192.168.93.133与192.168.93.134上的redis要启动
并需要关闭防火墙service iptables stop
6.测试
17.openresty模版渲染介绍
导入lua-resty-template
下载:http://luarocks.org/modules/bungle/lua-resty-template
将template.lua文件复制到openresty/lualib/resty/目录下
示例
nginx.conf
设置模版路径:set $template_root /usr/local/openresty/nginx/html/remplates;
设置mimeType类型:default_type text/html;
导入lua文件:content_by_lua_file /usr/local/openresty/nginx/conf/*.lua
lua脚本文件
local template = require “rest.template”
content={
message = “Hello,World!”,
names = {“james”,”fox”,”tony"}
}
template.render(“demo.html”,content);
18.商品详情页展示
Java生成静态页面放到nginx目录下(使用freemarker)
local template = require "resty.template" --调用模版
local redis = require “resty.redis_iresty”
local red = redis:new()
local msg = red:get("num")
if ngx.null == msg then
return ngx.say("获取库存失败")
end
local context = {
title = "京东商品",
-- 从redis中获取库存信息,在页面中显示
num = msg
}
local request_uri = ngx.var.request_uri
template.render(string.sub(request_uri,2),context);