Skip to content
🌹 基于OpenResty编写一个MVC模式的WEB项目 V0.01
Lua HTML JavaScript Other
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea
application
bin
conf
logs
lualib
public
template
.gitignore
LICENSE
README.md

README.md

Markdown

Wiki manual

https://github.com/Tinywan/lua_project_v0.01/wiki

Project structure

.
├── application                    -- 业务代码
│   ├── api
│   │   ├── live
│   │   └── users.lua
│   ├── controller                 -- 业务控制器
│   │   ├── live_redis_cache.lua
│   │   ├── upstream_backend.lua
│   │   └── web_socket_redis.lua
│   ├── model
│   │   └── Products.lua
│   ├── swoole
│   │   └── websocket-server.php
│   ├── waf
│   │   ├── init.lua
│   │   ├── install.sh
│   │   ├── wafconf
│   │   └── waf.lua
│   └── zabbix
│       └── install-record01.conf
├── bin                             -- 启动脚本
│   ├── doc2unix.sh
│   └── start.sh
├── conf                            -- 配置文件
│   ├── domains
│   │   └── nginx_live.conf
│   ├── fastcgi_params
│   ├── nginx.conf
│   ├── nginx.conf.default
│   └── nginx_lua_upstream.conf
├── logs                            -- 日志文件 
│   ├── 123.txt
│   ├── error.log
│   └── nginx.pid
├── lualib                          -- 官方Lua库
│   ├── cjson.so
│   ├── item
│   │   ├── common.lua
│   │   └── items.lua
│   ├── live                         -- 自定义公共部分Lua文件
│   │   └── common.lua
│   ├── ngx
│   │   ├── ssl
│   │   └── ssl.lua
│   ├── rds
│   │   └── parser.so
│   ├── redis
│   │   └── parser.so
│   ├── resty
│   │   ├── http_headers.lua
│   │   ├── http.lua
│   │   ├── upstream
│   │   └── websocket
│   └── vendor                      -- 第三方Lua库
│       ├── config.lua
│       ├── dkjson.lua
│       ├── helper.lua
│       ├── ip_check.lua
│       ├── ip_location.lua
│       └── mysql_fun.lua
├── public                          -- 公共静态文件
│   ├── bootstrap
│   │   ├── css
│   │   ├── fonts
│   │   ├── images
│   │   └── js
│   ├── data
│   │   └── location_ip_db.dat
│   ├── images
│   │   ├── github
│   │   ├── tinywan_title.png
│   │   └── yinzhang.png
│   ├── video-js
│   │   ├── videodemo.png
│   │   ├── video.js
│   │   └── video-js.swf
│   └── websocket
│       └── public
├── README.md
└── template                         -- 静态模板
    ├── index
    │   └── index.html
    ├── live
    │   ├── 404.html
    │   ├── crossdomain.xml
    │   ├── index.html
    │   ├── videodemo.png
    │   └── wesocket.html
    ├── product
    │   ├── footer.html
    │   ├── header.html
    │   ├── index2.html
    │   ├── index.html
    │   ├── item.html
    │   └── product_list.html
    ├── waf
    │   ├── index.html
    │   └── waf.php
    └── websocket
        ├── index.html
        ├── index.php
        ├── js
        └── websocket.html

Openresty Installation

  • 如何编译一个高性能 OpenResty
  • Prerequisites:
    apt-get install libreadline-dev libncurses5-dev libpcre3-dev \
    libssl-dev perl make build-essential
    
  • Building:
    wget https://openresty.org/download/openresty-1.11.2.3.tar.gz
    tar xvf openresty-1.11.2.1.tar.gz
    cd openresty-1.11.2.1
    ./configure --prefix=/opt/openresty \
                --with-luajit \
                --without-http_redis2_module \
                --with-http_iconv_module \
                --with-http_postgres_module 
    make -j2
    sudo make install
  • error
    • 错误1:you need to have ldconfig in your PATH env when enabling luajit.
    • 解决办法:
      sudo apt-get install luajit
      whereis luajit
      luajit: /usr/bin/luajit /usr/share/man/man1/luajit.1.gz
      
      ./configure --prefix=/opt/openresty \
                  --with-luajit=/usr/bin/luajit \
                  --without-http_redis2_module \
                  --with-http_iconv_module \
                  --with-http_postgres_module 
      make -j2
      sudo make install

nginx.conf, the Nginx web server configuration

user  www www;
worker_processes  8;

pid        logs/nginx.pid;
error_log log/error.log error;
worker_rlimit_nofile 204800;

events {
    use epoll;
    worker_connections  204800;
}

http {
    include       /opt/openresty/nginx/conf/mime.types;
    default_type  text/html;
    charset  utf-8;
    lua_package_path "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/lualib/?.lua;;";  #lua 模块
    lua_package_cpath "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/lualib/?.so;;";  #c模块
    include "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/conf/domains/*";
}

How to use

  • 新建文件夹同时下载项目:
    # 切换到 该目录,如果没有请重新建立
    www@iZ238xopqw6Z:~$ pwd
    /home/www
    git clone -b v0.03 https://github.com/Tinywan/lua_project_v0.01.git
  • 修改主配置文件:lua_project_v0.01/conf/nginx.conf 的路径,以下的/home/修改为项目所在路径
    lua_package_path "/home/lua_project_v0.01/lualib/?.lua;/home/lua_project_v0.01/application/controller/?.lua";#lua 模块
    lua_package_cpath "/home/lua_project_v0.01/lualib/?.so;;";          #  c模块
    include "/home/lua_project_v0.01/conf/domains/*";
  • 测试配置文件:test.conf
  • 修改项目路径变量:set $project_path /home/;
    • 日志文件路径不支持变量(暂时需要修改,以后直接做跨域保存就可以了):access_log "/home/lua_project_v0.01/logs/demo_access.log";
  • 启动脚本
    • 赋予权限(655):chmod +x /start.sh ,
    • 配置成功运行结果如下:
      /home/lua_project_v0.01/conf# ../bin/start.sh start
       [ Stop OK ] 
      nginx: the configuration file /home/lua_project_v0.01/conf/nginx.conf syntax is ok
      nginx: configuration file /home/lua_project_v0.01/conf/nginx.conf test is successful
       [ Start OK ]
  • 测试流程是否跑通:curl http://127.0.0.1/,输出:Hello! lua_project_v0.01,表示环境配置成功

branch list

  • master分支已经很稳定了,将不再提交代码,以后将从以下分支提交
  • 公司company分支
  • 家里home分支

config list

  • API接口专用(8686):api.conf
  • Demo测试专用(8080):nginx_demo.conf
  • 活动直播专用(8088):nginx_live.conf
  • Waf防火墙专用(8082):waf.conf
  • 商品列表专用(8083):nginx_product.conf

error infomation

  • 解决nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
  • 错误日志:[crit] 3478#0: *5 connect() to unix:/var/run/php7.0.9-fpm.sock failed (13: Permission denied)
    • 修改php-fpm.conf配置文件
    listen.owner = nginx
    listen.group = nginx
    listen.mode = 0660
    • 跑nginx的用户是nginx,而/var/run/php7.0.9-fpm.sock 这个文件。监听的nginx用户没有该权限,导致nginx无法访问/var/run/php5-fpm.sock这个文件,自然监听就失去了效果。

helper 助手

  • 获取http get/post 请求参数:helper.http_args()
  • 字符串分割:helper.split()
  • 删除空格:helper.ltrim() / rtrim() / trim()
  • json 解析的异常:helper.cjson_decode(str2)
    • 错误返回nil,成功返回解析后的json字符串
    • 如何调用
        local helper = require 'vendor.helper'
        local str1  = '{"hobby":{"name":"tinywan","age":24},"is_male":false}'    -- 写法1
        local str2  = [[ {"hobby":{"name":"tinywan","age":24},"is_male:false} ]] -- 写法2   
        local obj_obj = helper.cjson_decode(str2)
        if not json_str then
            ngx.say('cjson_decode error')
        else
            ngx.say(helper.format_table(json_str))
        end

Mysql 数据库操作

  • 添加
    local mysql = require 'vendor.mysql_fun'
    local cjson = require 'cjson'
    data = { name = "TinyWAN", address = "HeilongJiang", age = "26" }
    local result = mysql.add(data.name,data.address,data.age)
    ngx.print(cjson.encode(result))
  • 查询
    local result = mysql.select(3)
    ngx.print(cjson.encode(result))
  • 修改
    local result = mysql.update(3,"TinTinAIAI")
    ngx.print(cjson.encode(result))
  • 删除
    local result = mysql.delete(3)
    ngx.print(cjson.encode(result))
  • 数据返回结果:
    • ✔️ 成功
      {
          "error_code": 200,
          "message": "add successfully"
      }
    • ✖️ 失败
      {
          "error_code": 504,
          "message": "failed to delete"
      }
  • mysql_fun.lua
  • 封装遇到的问题:
    • nginx 错误日志总是出现这个:lua entry thread aborted: runtime error: attempt to yield across C-call boundary
    • 解决办法:ngx_lua 连接mysql
    • 封装好的文件:/vendor/mysql_fun.lua
    • 封装好调用的时候一直出现这个:curl: (52) Empty reply from server
    • 解决办法,在每次增删改查的时候都要调用数据库连接的这个方法数据库连接connect_db()方法就可以了
      function _M.update(id, name)
          connect_db()
      end

📅

2017年05月07日 星期日

  • 创建项目、项目架构搭建、目录结构调整
  • 添加新功能
    • 简单的Redis数据库操作
    • 根据IP地址获取具体城市信息(@icowan)
    • lua-resty-shell库的使用

2017年05月08日 星期一

  • 添加功能:lua-resty-websocket 官方测试案例
  • 添加功能:WebSocket系统负载统计

2017年05月10日 星期三

2017年05月11日 星期四

  • Mysql 数据库添加
    • 错误提示:bad result: Data too long for column 'name' at row 1: 1406: 22001.,插入字段超过表定义大小

2017年05月14日 星期日

  • Swoole WebSocket 测试
    • 开启服务:php /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/swoole/websocket-server.php
    • 客户端测试:http://127.0.0.1/clinet.html

2017年05月15日 星期一

  • 添加Nginx 启动脚本:start.sh
    • 开启Nginx:/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/bin/start.sh
    • 如果已经开始Nginx,则执行start.sh 可以重新加载配置文件
  • 添加Nginx 停止脚本:stop.sh
    • 停止Nginx:/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/bin/stop.sh
  • 脚本运行错误:

2017年05月17日 星期三

  • ngx_lua_waf 安装使用(ngx_lua_waf是一个基于lua-nginx-module(openresty)的web应用防火墙)

    • ngx_lua_waf github 地址
    • 安装步骤
      1. 下载源码到某一目录:复制目录到application下面,同时重命名waf
      2. 命令:cp -R ngx_lua_waf /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/waf
      3. 移动源文件目录中的config.lua文件到../lualib/vendor
      4. 修改waf 目录下的init.lua文件的第一行:require 'config'修改为require 'vendor.config'
      5. domains目录下,新建文件waf.conf,添加以下内容
            lua_shared_dict limit 10m;
            init_by_lua_file  "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/waf/init.lua";
            access_by_lua_file "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/waf/waf.lua";
            
            server {
                listen       8082;
                server_name  localhost;
                index  index.php index.html index.htm;
                access_log  /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/logs/waf_access.log;
                error_log /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/logs/waf_error.log error;
            
                set $web_root /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/template/waf;
                root $web_root;
            
                location / {
                    try_files $uri $uri/ /index.php?$args;
                }
            
                location ~ \.php$ {
                    fastcgi_pass   unix:/var/run/php7.0.9-fpm.sock;
                    fastcgi_index  index.php;
                    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                    include        fastcgi_params;
                }
            }
      6. 重启Nginx即可
       tinywan@tinywan:~$ /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/bin/start.sh 
       [ Nginx running ] 
       nginx: the configuration file /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/conf/nginx.conf syntax is ok
       nginx: configuration file /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/conf/nginx.conf test is successful
       [ Nginx has reload ]
      1. 可能会遇到的错误
        • [1]nginx: [emerg] open() "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/conf/fastcgi_params" failed

          解决:cp fastcgi_params /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/conf/fastcgi_params

        • [2]FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

          解决:查看waf.conf配置信息是否正确

  • 修改文件:config.lua

    black_fileExt={"php","jsp"}
    ipWhitelist={"127.0.0.1"}
    --ipBlocklist={"1.0.0.1"}
    ipBlocklist={"192.168.127.133"}
  • 测试一:http://127.0.0.1:8082/waf.php?id=../etc/passwd&name=Tinywan

    • waf_ip_blaklist3
  • 测试二:http://192.168.127.133:8082/waf.php?id=../etc/passwd&name=Tinywan

    • waf_ip_blaklist2
  • 💩💩 在提交代码的时候waf目录一直提交不了,提示:modified: xxx(modified content, untracked content), 原来在waf目录下有个.git 目录,删除.git目录,重新git add 就可以了

2017年05月19日 星期五

  • 第一版采用单模块设计
  • 简单的MVC模式,目录、命名约定(Phalcon MVC)
    • Model(模型)负责在数据库中存取数据
    • View(视图)是应用程序中处理数据显示的部分
    • Controller(控制器)通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据
  • 第一个简单的 mvc 模式的文件路径访问
  1. 配置文件:nginx_product.conf

    #upstream
    upstream item_http_upstream {
        server 192.168.1.1 max_fails=2 fail_timeout=30s weight=5;
        server 192.168.1.2 max_fails=2 fail_timeout=30s weight=5;
    }
    
    #缓存 共享字典配置
    lua_shared_dict item_local_shop_cache 600m;
    
    # server product
    server {
        listen       8082;
        server_name  127.0.0.1;
        charset gbk;
        index  index.html index.htm;
        access_log  /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/logs/product_access.log;
        error_log /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/logs/product_error.log error;
    
        #加载模板文件
        set $template_root /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/template;
    
        #url映射
        location ~* "^/product/(\d+)\.html$" {
            rewrite /product/(.*)    http://127.0.0.1:8082/$1 permanent;
        }
    
        # chapter
        location ~* "^/(\d{6,12})\.html$" {
            default_type text/html;
            lua_code_cache on;
            content_by_lua_file "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/controller/ProductController.lua";
        }
    }
  2. 当我们访问页面:http://127.0.0.1:8082/13669361192.html
    将交给lua_project_v0.01/application/controller/ProductController.lua处理

    curl -k http://127.0.0.1:8082/13669361192.html
    Hello ProductController.lua
    uri = /13669361192.html
  3. 项目入口搞定 🌺 🌺 🌺 🌺

  • 💐 lua-resty-template 的使用

        #加载模板文件
        set $template_root "/mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/template/product";
      
        location /template_test {
           default_type 'text/html';
           content_by_lua '
                local template = require "resty.template"
                template.render(chatroom.html, { message = "Hello, World!" })
           ';
        }
  • 🌼 resty.template渲染模板,通过ngx API输出内容到指定的html页面

    • Markdown

2017年05月20日 星期六

  • helper类的封装
    • Example
      local helper = require 'vendor.helper'
      local array = helper.split('a,b,v,b',',')
      for key,value in ipairs(array)
      do
        ngx.say(key, value)
      end
  • dkjson 库的加入 👏 👏 👏
    • 常用Lua开发库2-JSON库、编码转换、字符串处理
    • Example
      local dkjson = require 'vendor.dkjson'
      --lua对象到字符串
      local obj = {
          id = 110,
          name = "Tinywan",
          age = 24,
          is_male = false,
          hobby = {"film", "music", "read"}
      }
      local str = dkjson.encode(obj, {indent = true})
      ngx.say(str, "<br/>")
  • 获取Redis数据库数据渲染到html模板页面显示
    • 数据显示、文件加载都合适
    • 问题:JS、CSS样式文件路径不合适
  • Nginx+Lua逻辑开发 Redis 做为页面缓存
    • Nginx 配置文件:nginx_live.conf
    • Lua 文件:LiveRedisCacheController.lua
    • http://127.0.0.1:8088/ad/133456 有缓存返回:{"content":"Redis Cache Data"}
    • http://127.0.0.1:8088/ad/13345 没有缓存返回:{"content":"MYSQL DATA \n"}
  • ✔️ 发布一个V0.01 版本 ✏️ ✏️ ✏️ ✏️

2017年05月21日 星期日

  • 历史遗留问题解决:模板页面的JS、CSS样式文件加载不合适,忘记了Nginx处理静态资源的配置,添加以下代码OK
    #配置Nginx动静分离,定义的静态页面直接从Nginx发布目录读取。
    location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
    {
        root /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/template/info;
        #expires定义用户浏览器缓存的时间为7天,如果静态页面不常更新,可以设置更长,这样可以节省带宽和缓解服务器的压力
        expires      7d;
    }
  • 访问页面:http://192.168.127.133:8083/2017TinywanInfo可以得到响应内容

2017年05月22日 星期一

  • 标准os库,待补充
    • os.rename(oldname, newname):文件重命名
    • os.remove(filename):删除一个文件
    • os.execute(cmd):os.execute可运行一条系统命令,类似于C语言的system函数,os.execute("mkdir /tmp/cq")
    • os.exit(code):中止当前程序的执行,code参数默认值为true。
    • os.getenv(variable):返回环境变量的值,如果不存在,返回nil,print(os.getenv('HOME')) -- /root
    • os.time(tb):返回一个指定时间点的UNIX时间戳,如不带参数调用的话,就返回当前时间点的UNIX时间戳

2017年05月23日 星期二

  • API 的设计
    • 版本:0.1
    • 专用端口:8686
    • 配置文件
      location ~ ^/app/([-_a-zA-Z0-9/]+)$ {
          set $id $1;
          content_by_lua_file /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/api/${id}.lua;
      }
    • curl访问地址:curl http://127.0.0.1:8686/0.1/app/web文件名
    • 访问案例:curl http://127.0.0.1:8686/0.1/app/web,将会执行web.lua文件
  • 如何使用API接口
    • 创建对象:
      curl -X POST \
        -H "X-LC-Id: 558e20cbe4b060308e3eb36c" \
        -H "X-LC-Key: cbe4b06030558e208e3eb36c20cbe4b060308e3eb36c" \
        -H "Content-Type: application/json" \
        -d '{"name": "Tinywan","age": "26","tel": 13669361192}' \ 
        http://127.0.0.1:8686/0.1/users
    • 查询信息:
      curl -X GET \
        -H "X-LC-Id: {{appid}}" \
        -H "X-LC-Key: {{appkey}}" \
        -G \
        --data-urlencode 'id=9090' 
        http://127.0.0.1:8686/0.1/users
    • 更新对象:
      curl -X PUT \
        -H "X-LC-Id: {{appid}}" \
        -H "X-LC-Key: {{appkey}}" \
        -H "Content-Type: application/json" \
        -d "name=tinywan&age=26" \	
        http://127.0.0.1:8686/0.1/users
      
    • 删除对象:
      curl -X DELETE \
         -H "X-LC-Id: {{appid}}" \
         -H "X-LC-Key: {{masterkey}},master" \
         -G \
         --data-urlencode 'id=10' \
         http://127.0.0.1:8686/0.1/users 

2017年05月25日 星期四

  • 活动直播接口 API 数据访问Redis,如果没有则回源到后端Mysql数据库
  • nginx.conf配置
    # 直播接口数据
    location ~ ^/0.1/live/([-_a-zA-Z0-9/]+) {
        content_by_lua_file /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/api/$1.lua;
    }
    
    # Redis 没有缓存数据则后端Mysql查询数据
    location /sub {
        internal;
        proxy_pass http://127.0.0.1:8686/backend/mysql;
    }
    
    # Backend Mysql Data
    location /backend/mysql {
         content_by_lua_block {
             ngx.say("backend post: Mysql ")
         }
    }
  • 请求Example:
    • 访问如:http://127.0.0.1:8686/0.1/live/live_redis_mysql?id=1122334即可得到结果。而且注意观察日志,第一次访问时不命中Redis,回源到Mysql;第二次请求时就会命中Redis了。
    • 第一次访问时将看到../logs/api_error.log输出类似如下的内容,而第二次请求相同的url不再有如下内容
       live_redis_mysql.lua:122: redis not cache content, Content comes from mysql , id : 1122334, 
       live_redis_mysql.lua:125: Content comes from Redis, id = 1122334, 
    • live_redis_mysql.lua

2017年05月26日 星期五

2017年05月31日 星期三

  • 虚拟主机的项目根目录自定义,方便灵活修改
  • 配置案例:
    server {
        listen       8080;
        # 定义项目根目录,在此本项目目录为虚拟机目录,你可以自定义为 /home/www/
        set $project_path /mnt/hgfs/Linux-Share/Lua/;  
        location /cjson_decode_pcall {
            content_by_lua_file "${project_path}lua_project_v0.01/application/demo/cjson.lua";
        }

2017年06月2日 星期五

  • API接口先查询Redis缓存数据,如果没有则到Mysql数据库查询获取,同时缓存数据到Redis中
  • 访问地址返回数据:
tinywan@tinywan:~$ curl http://127.0.0.1:8686/0.1/live/live_redis_to_mysql?id=3
{"1":{"age":"24","name":"tinywan","address":"China","id":"3"},"Data_Sources":"Redis Cache Content"}

2017年06月4日 星期日

  • 获取Get 参数查询Mysql数据同时把数据在模板页面显示出来
  • 参考代码:
    local template = require "resty.template"
    local mysql = require 'vendor.mysql_fun'
    local helper = require "vendor.helper"
    local arg = helper.http_args()
    local live_id = arg.live_id
    local res = mysql.select(live_id)
    local address = ""
    if res.error_code == 200 then
        address = res.result.address
    end
    template.render(chatroom.html, { hls_address = address })
  • websocket_shell

2017年06月07日 星期三

  • 商品的详情页页面数据显示(数据存储(Redis)的时候使用json格式存储,键约定:ITEM:${Product_Id})
  • 配置文件:nginx_product.conf
  • 控制器文件:ItemController.lua
  • 访问路径:http://127.0.0.1:8087/item/13669361192 即可把Redis的缓存数据渲染到html页面
  • 所有的静态文件罗列在一个地方:
    • Nginx配置:root /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/public;
    • Html页面加载:<script src="/video-js/videojs-contrib-hls.min.js"></script>
  • 下来要做的就是动态加载模板和数据、缓存处理...

2017年06月08日 星期四

  • 一个简单的http请求获取数据,先Redis,再后台数据API,然后缓存在Redis(待优化,现在只是跑通一个DEMO)
  • location_lua_redis_backend
  • 访问地址:curl http://127.0.0.1:8088/live/1108,请注意查看Log日志文件的变化
  • 主要代码
    # 入口Lua文件的调用
    location ~ ^/live/(\d+)$ {
        set $id $1;
        content_by_lua_file "lua_project_v0.01/application/controller/LiveRedisCacheController.lua";
    }
    
    # 请求后端服务器的API接口查询数据,接口返回数据格式为Json格式
    location ~ /openapi/(.*) {
        internal;
        proxy_pass http://www.baidu.com;
    }
  • 做个压力测试(主要是Redis连接数,并发太多将会出现超时问题,netstat 查看Redis连接数,好多"TIME OUT"),测试很糟糕的,QPS好低哦!
  • 这块一定要优化!80%就大工搞成了
  • 修改后端API请求方式,由ngx.location.capture 转换为:resty.http
    • 可能出现的错误:resty.http API request error :no resolver defined to resolve "sewise.baidu.com"
    • 解决办法,nginx.conf server节增加dns解析resolver 8.8.8.8 114.114.114.114 valid=3600s;
  • 别人的建议:
    • lua_redis
  • 添加二级缓存(ngx.cache)
    • 访问地址:http://127.0.0.1:8088/live/1063
    • 缓存记录表
      +-------------+    +-------------+    +-------------+    +-------------+
      |   第一次访问  |--->|  ngx_cache  |--->| redis_cache |--->| backend API |
      +-------------+    +-------------+    +-------------+    +-------------+
                                                                     |                                         
      +-------------+    +-------------+    +-------------+          |
      |   第二次访问  |--->|  ngx_cache  |--->| redis_cache |<---------+
      +-------------+    +-------------+    +-------------+    
                                                   |
      +-------------+    +-------------+           |
      |   第三次访问  |--->|  ngx_cache  |<----------+
      +-------------+    +-------------+ 
    • 第一次访问日志记录
       [lua] CacheController.lua:145: ngx_cache not found content, request redis  db , id : 1066,
       [lua] CacheController.lua:61: read_redis(): get redis content error : LIVE_TABLE : 1066
       [lua] CacheController.lua:151: redis not found content, back to backend API , id : 1066
       [lua] CacheController.lua:133: read_http(): content from backend API id : 1066
    • 第二次访问日志记录
      [lua] CacheController.lua:145: ngx_cache not found content, request redis  db , id : 1066
      [lua] CacheController.lua:70: read_redis(): content from redis LIVE_TABLE:1066
    • 第三次到第N次访问日志记
      [lua] CacheController.lua:39: get_cache(): content from ngx.cache id : LIVE_TABLE:1066
      [lua] CacheController.lua:39: get_cache(): content from ngx.cache id : LIVE_TABLE:1066
      [lua] CacheController.lua:39: get_cache(): content from ngx.cache id : LIVE_TABLE:1066
    • 解决缓存失效风暴 lua-resty-lock [二级缓存]
    • 缓存时间问题:ngx.cache目前默认为1s
  • redis使用连接池、锁机制、二级缓存,全部为官方代码,第三方封装好的redis_iresty没有使用

2017年06月16日 星期五

  • resty.websocket.serverresty.redis 实现聊天室功能
  • 请求访问地址:http://192.168.18.180:8088/live/1138
  • WebSocketRedisController.lua 文件
  • live_room.png
  • 待解决 lua tcp socket read timed out 问题,
  • 需要深入研究的API ngx.thread.spawn 轻线程知识的学习,

openresty进行了简化成了7个阶段

  • set_by_lua: 流程分支判断,判断变量初始哈
  • rewrite_by_lua: 用lua脚本实现nginx rewrite
  • access_by_lua: ip准入,是否能合法性访问,防火墙
  • content_by_lua: 内存生成
  • header_filter_by_lua:过滤http头信息,增加头信息
  • body_filter_by_lua: 内容大小写,内容加密
  • log_by_lua: 本地/远程记录日志
  • 其实可以只用 content_by_lua,所有功能都在该阶段完成,也是可以的

功能列表

简单的Redis数据库操作

  • 通过引入已经封装好的Redis类操作Redis数据
  • 直接运行curl:curl http://127.0.0.1/get_redis_iresty
  • 官方短连接和长连接测试已通过(本地环境)
  • 官方短连接和长连接测试已通过(本地环境)

根据IP地址获取具体城市信息

  • 根据IP地址,获取具体IP地址的城市详细信息
  • 直接运行curl:curl http://127.0.0.1/test_ip_location?ip='122.228.95.112'

lua-resty-shell 库

  • 执行shell命令
  • 获取Linux的CPU信息:curl http://127.0.0.1/shell_test

lua-resty-websocket 官方测试案例

  • 服务端文件lua_websocket_server.lua,客户端接受文件public/index_default.html,JS代码public/static/stats_default.js
  • 服务端配置location
       location /lua_websocket_server {
           default_type text/html;
           content_by_lua_file /mnt/hgfs/Linux-Share/Lua/lua_project_v0.01/application/lua_websocket_server.lua;
       }
  • 客户端,通过jsconsole.log(e.data) 打印接收到的数据,这类我们可以接受到服务端发送的消息
-- 服务端发送文本
bytes, err = wb:send_text("Hello world Tinywan")

--客户端接受数据,通过浏览器Console 可以看到以下数据
Hello world Tinywan
stats_default.js:70 Blob {size: 17, type: ""}
stats_default.js:65 disconnect
stats_default.js:60 connect

websocket系统负载统计

  • 基于lua-resty-websocket实现系统负载监控
  • 使用第三方编写的websocket_shell.lua(原本叫shell.lua) 一个库文件
  • 第三方库或者文件引入:local shell = require 'vendor.websocket_shell'
  • 注意:在这里并没有用到lua-resty-shell 库,有时间整合到一起去
  • 效果预览图: websocket_shell

nginx proxy_cache 缓存配置

                   +-------------+
                   |    uplink   |
                   +-------------+
                          |
                          +
    MASTER            keep|alived         BACKUP
172.29.88.224      172.29.88.222      172.29.88.225
+-------------+    +-------------+    +-------------+
|   nginx01   |----|  virtualIP  |----|   nginx02   |
+-------------+    +-------------+    +-------------+
                          |
       +------------------+------------------+
       |                  |                  |
+-------------+    +-------------+    +-------------+
|    web01    |    |    web02    |    |    web03    |
+-------------+    +-------------+    +-------------+


+-------------+    +-------------+    +-------------+    +-------------+
|   第一次访问  |--->|  ngx_cache  |--->|   redis     |--->| backend API |
+-------------+    +-------------+    +-------------+    +-------------+

+-------------+    +-------------+    +-------------+ 
|   第二次访问  |--->|  ngx_cache  |--->|   redis     |
+-------------+    +-------------+    +-------------+    

+-------------+    +-------------+ 
|   第三次访问  |--->|  ngx_cache  |
+-------------+    +-------------+   
You can’t perform that action at this time.