├── .gitignore ├── README.md ├── SUMMARY.md ├── advanced ├── oo.md ├── packages.md └── page_cache.md ├── apis ├── bootstrap.md ├── buildin.md ├── controller.md ├── error.md ├── plugins.md ├── route.md └── view.md ├── book.json ├── bootstrap.md ├── buildin.md ├── cconfig.md ├── cover.jpg ├── error.md ├── install ├── 0_1_rc3.md ├── 0_1_rc4.md ├── 0_1_rc5.md ├── 0_1_rc6.md ├── 0_1_rc7.md ├── or_luarocks.md └── va_c.jpeg ├── intro ├── index_structure.md ├── overview.md ├── va_c.jpeg └── vanilla_start.md ├── libs └── cookie.md ├── openresty ├── or_doc.md └── or_doc │ ├── coroutine.md │ ├── ngx_ thread.md │ ├── ngx_config.md │ └── ngx_timer.md ├── plugins.md ├── quick_learning ├── add_controller.md ├── debug.md ├── hello_world.md ├── models_dao.md └── models_service.md ├── route.md ├── route.png ├── sundry ├── 3rd_party_pkg.md ├── gdb.md ├── nginx_phrase.md ├── ngx_re.md ├── openresty-cn.png ├── qcon2015brokenperformancetools │ ├── 1.jpg │ ├── 10.jpg │ ├── 100.jpg │ ├── 101.jpg │ ├── 102.jpg │ ├── 103.jpg │ ├── 104.jpg │ ├── 105.jpg │ ├── 106.jpg │ ├── 107.jpg │ ├── 108.jpg │ ├── 109.jpg │ ├── 11.jpg │ ├── 110.jpg │ ├── 111.jpg │ ├── 112.jpg │ ├── 113.jpg │ ├── 114.jpg │ ├── 115.jpg │ ├── 116.jpg │ ├── 117.jpg │ ├── 118.jpg │ ├── 119.jpg │ ├── 12.jpg │ ├── 120.jpg │ ├── 121.jpg │ ├── 122.jpg │ ├── 123.jpg │ ├── 124.jpg │ ├── 125.jpg │ ├── 126.jpg │ ├── 127.jpg │ ├── 128.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.jpg │ ├── 19.jpg │ ├── 2.jpg │ ├── 20.jpg │ ├── 21.jpg │ ├── 22.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── 25.jpg │ ├── 26.jpg │ ├── 27.jpg │ ├── 28.jpg │ ├── 29.jpg │ ├── 3.jpg │ ├── 30.jpg │ ├── 31.jpg │ ├── 32.jpg │ ├── 33.jpg │ ├── 34.jpg │ ├── 35.jpg │ ├── 36.jpg │ ├── 37.jpg │ ├── 38.jpg │ ├── 39.jpg │ ├── 4.jpg │ ├── 40.jpg │ ├── 41.jpg │ ├── 42.jpg │ ├── 43.jpg │ ├── 44.jpg │ ├── 45.jpg │ ├── 46.jpg │ ├── 47.jpg │ ├── 48.jpg │ ├── 49.jpg │ ├── 5.jpg │ ├── 50.jpg │ ├── 51.jpg │ ├── 52.jpg │ ├── 53.jpg │ ├── 54.jpg │ ├── 55.jpg │ ├── 56.jpg │ ├── 57.jpg │ ├── 58.jpg │ ├── 59.jpg │ ├── 6.jpg │ ├── 60.jpg │ ├── 61.jpg │ ├── 62.jpg │ ├── 63.jpg │ ├── 64.jpg │ ├── 65.jpg │ ├── 66.jpg │ ├── 67.jpg │ ├── 68.jpg │ ├── 69.jpg │ ├── 7.jpg │ ├── 70.jpg │ ├── 71.jpg │ ├── 72.jpg │ ├── 73.jpg │ ├── 74.jpg │ ├── 75.jpg │ ├── 76.jpg │ ├── 77.jpg │ ├── 78.jpg │ ├── 79.jpg │ ├── 8.jpg │ ├── 80.jpg │ ├── 81.jpg │ ├── 82.jpg │ ├── 83.jpg │ ├── 84.jpg │ ├── 85.jpg │ ├── 86.jpg │ ├── 87.jpg │ ├── 88.jpg │ ├── 89.jpg │ ├── 9.jpg │ ├── 90.jpg │ ├── 91.jpg │ ├── 92.jpg │ ├── 93.jpg │ ├── 94.jpg │ ├── 95.jpg │ ├── 96.jpg │ ├── 97.jpg │ ├── 98.jpg │ └── 99.jpg └── qcon_2015_broken_performance_tools.md ├── update.md ├── va_c.jpeg └── vanilla_user_practice ├── README.md ├── shi_yong_jing_yan.md └── yong_hu_lie_biao.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf 17 | *.plist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##香草/Vanilla 2 | *香草/Vanilla是一个基于Openresty实现的高性能Web应用开发框架.* 3 | 4 | ![Vanilla](http://m1.sinaimg.cn/maxwidth.300/m1.sinaimg.cn/120d7329960e19cf073f264751e8d959_2043_2241.png) 5 | 6 | ### *邮件列表* 7 | - vanilla-en 8 | - vanilla-devel 9 | - vanilla中文邮件列表 10 | 11 | ### *推荐始终使用最新版的Vanilla* 12 | *当前Vanilla最新版本0.1.0.rc6,支持命令:* 13 | 14 | - vanilla-0.1.0.rc6(*你没看错,自0.1.0.rc5起,vanilla的命令行和框架代码都带着版本号,方便多版本共存,也方便框架升级*) 15 | - v-console-0.1.0.rc6 16 | 17 | ## 特性 18 | 19 | - 提供很多优良组件诸如:bootstrap、 router、 controllers、 models、 views。 20 | - 强劲的插件体系。 21 | - 多 Application 部署。 22 | - 多版本框架共存,支持便捷的框架升级。 23 | - 一键 nginx 配置、 应用部署。 24 | - 便捷的服务批量管理。 25 | - 你只需关注自身业务逻辑。 26 | 27 | ## 安装 28 | 29 | ##### *Vanilla-V0.1.0-rc4.1 或之前版本的 Vanilla 安装请参见 : [README-V0.1.0-rc4.1.md](README/README-zh-V0.1.0-rc4.1.md)* 30 | 31 | ``` bash 32 | $ ./setup-framework -v $VANILLA_PROJ_ROOT -o $OPENRESTY_ROOT #运行 ./setup-framework -h 查看更多参数细节 33 | ``` 34 | 35 | ## 快速开始 36 | 37 | **部署你的第一个Vanilla Application** 38 | 39 | ``` bash 40 | $ ./setup-vanilal-demoapp [-a $VANILLA_APP_ROOT -u $VANILLA_APP_USER -g $VANILLA_APP_GROUP -e $VANILLA_RUNNING_ENV] #运行 ./setup-vanilal-demoapp -h 查看更多参数细节 41 | ``` 42 | 43 | **启动你的 Vanilla 服务** 44 | 45 | ``` bash 46 | $ ./$VANILLA_APP_ROOT/va-appname-service start 47 | ``` 48 | 49 | ## 更多信息 50 | 51 | - 参见 [文档](https://idevz.gitbooks.io/vanilla-zh/content/index.html) 52 | 53 | 54 | ### 社区组织 55 | #### *QQ群&&微信公众号* 56 | - *Openresty/Vanilla 开发 1 群:205773855* 57 | - *Openresty/Vanilla 开发 2 群:419191655* 58 | - *Openresty 技术交流 1 群:34782325* 59 | - *Openresty 技术交流 2 群:481213820* 60 | - *Openresty 技术交流 3 群:124613000* 61 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 62 | 63 | ![vanilla](va_c.jpeg) 64 | 65 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [简介](README.md) 4 | * 快速上手 5 | * [Hello World](quick_learning/hello_world.md) 6 | * [如何调试](quick_learning/debug.md) 7 | * [如何新增一个Controller](quick_learning/add_controller.md) 8 | * [如何使用models/dao](quick_learning/models_dao.md) 9 | * [如何使用models/service](quick_learning/models_service.md) 10 | * APIs 11 | * [配置](cconfig.md) 12 | * [Bootstrap](apis/bootstrap.md) 13 | * [Controllers](apis/controller.md) 14 | * [模板引擎](apis/view.md) 15 | * [插件](apis/plugins.md) 16 | * [路由](apis/route.md) 17 | * [异常处理](apis/error.md) 18 | * [内建类](apis/buildin.md) 19 | * Libs 20 | * [Cookie](libs/cookie.md) 21 | * 进阶 22 | * [页缓存](advanced/page_cache.md) 23 | * [面向对象](advanced/oo.md) 24 | * [Vanilla 包开发](advanced/packages.md) 25 | * OpenResty 26 | * [OR文档精炼](openresty/or_doc.md) 27 | * [ngx.timer](openresty/or_doc/ngx_timer.md) 28 | * [ngx.config](openresty/or_doc/ngx_config.md) 29 | * [coroutine](openresty/or_doc/coroutine.md) 30 | * [ngx.thread](openresty/or_doc/ngx_thread.md) 31 | * ChangeLogs 32 | * [vanilla-0.1.0.rc7](install/0_1_rc7.md) 33 | * [vanilla-0.1.0.rc6](install/0_1_rc6.md) 34 | * [vanilla-0.1.0.rc5](update/0_1_rc4_rc5.md) 35 | * [vanilla-0.1.0.rc4](install/0_1_rc4.md) 36 | * [vanilla-0.1.0.rc3](install/0_1_rc3.md) 37 | * 杂项 38 | * [Nginx执行阶段](sundry/nginx_phrase.md) 39 | * [GDB 调试 OpenResty](sundry/gdb.md) 40 | * [OpenResty 正则示例收集](sundry/ngx_re.md) 41 | * [基于 OpenResty 安装 Luarocks](install/or_luarocks.md) 42 | * [Vanilla集成的一些优秀第三方包](sundry/3rd_party_pkg.md) 43 | * [QCon 2015 Broken Performance Tools](sundry/qcon_2015_broken_performance_tools.md) 44 | * Vanilla使用经验 45 | * [用户列表](vanilla_user_practice/yong_hu_lie_biao.md) 46 | 47 | -------------------------------------------------------------------------------- /advanced/oo.md: -------------------------------------------------------------------------------- 1 | ##面向对象的 Vanilla 2 | *Lua 提供了部分面向对象的语法糖,这仅仅能在开发中提供一个功能不完备的独立 Class 的使用,有 `self` 可以来引用 LUA 表的某些属性和方法,但是更多的面向对象特性,比如继承,比如类的构造等,LUA 支持的并不是非常好,日常的业务开发中,我们确实有些通用的逻辑可能需要复用,或者数据需要共享,需要有父子关系等等。所以我们在 Vanilla 中,简单封装了部分面向对象的特性,这里我们简单介绍其使用方法。* 3 | 4 | ###*一个简单的 Vanilla 类* 5 | *下面我们看一个例子:* 6 | 7 | #####*类定义* 8 | 9 | ```lua 10 | local LibA = Class("LibA") 11 | 12 | function LibA:idevzDo(params) 13 | local params = params or { lib_bb = 'idevzDo LibA'} 14 | return params 15 | end 16 | 17 | function LibA:__construct( data ) 18 | self.name = 'name-->' .. data.name 19 | self.sex = 'sex-->' .. data.sex 20 | end 21 | 22 | return LibA 23 | ``` 24 | 25 | *代码释意:* 26 | 27 | * `Class("LibA")` 声明一个 Vanilla 类,类名为 `LibA` 28 | * `LibA:__construct( data )` 提供了一个类 LibA 的构造器,并对相应的属性进行初始化 29 | 30 | #####*类使用* 31 | 32 | ```lua 33 | local LibA = LoadLibrary('aa') 34 | local liba_instance = LibA({name='idevz',sex='man'}) 35 | print_r(liba_instance.sex) 36 | ``` 37 | *执行结果 `sex-->man`* 38 | 39 | *代码释意:(类使用的时候需要注意,类的使用分为类文件的加载 `Load( 如这里的 LoadLibrary )` 和实例化 `LibA()`) 两个步骤* 40 | 41 | * `local LibA = LoadLibrary('aa')` 载入类名为 `LibA` 的类 42 | * `local liba_instance = LibA({name='idevz',sex='man'})` 传入表 `{name='idevz',sex='man'}` 对类进行相关的实例化 43 | * `liba_instance.sex` 是对实例属性的引用 44 | 45 | *注:载入和实例化也可以一步达成 `local liba_instance = LoadLibrary('aa')({name='idevz',sex='man'})`* 46 | 47 | 48 | ###*类继承* 49 | *下面我么定义一个类 LibB,并使之集成于 LibA* 50 | 51 | #####*类定义* 52 | 53 | ```lua 54 | local LibB = Class("LibB", LoadLibrary('LibA')) 55 | 56 | function LibB:__construct( data ) 57 | local data = data or {name='kk', sex='xxx'} 58 | data.sex = data.sex .. '-->son' 59 | self.parent:__construct(data) 60 | end 61 | 62 | return LibB 63 | ``` 64 | 65 | *代码释意:* 66 | 67 | * `Class("LibB", LoadLibrary('LibA'))` 声明一个 Vanilla 类,类名为 `LibB` 继承自类 `LibA` 68 | * `self.parent:__construct(data)` 构造器中调用父类的构造器 69 | 70 | #####*类使用* 71 | 72 | ```lua 73 | local LibB = LoadLibrary('LibB') 74 | local libb_instance = LibB({name='idevz',sex='man'}) 75 | print_r(libb_instance:idevzDo({doo='xxx'})['doo']) 76 | ``` 77 | *执行结果 `xxx`* 78 | 79 | *代码释意:* 80 | 81 | * `libb_instance:idevzDo` 调用父类的 `idevzDo` 方法 -------------------------------------------------------------------------------- /advanced/packages.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的包开发 2 | *可以使用任意 LUA 包的开发方式来开发 Vanilla 包(Controllers,Library,Dao,Services等),也可以使用 Vanilla 所提供的[面向对象](./oo.md) 方式进行开发* 3 | 4 | ###*对 Controller 使用继承和构造器* 5 | *下面我们看一个例子:* 6 | 7 | ```lua 8 | local IndexController = Class('controllers.index', 9 | LoadApplication('controllers.base')) 10 | 11 | function IndexController:__construct() 12 | self.parent:__construct() 13 | end 14 | 15 | return IndexController 16 | ``` 17 | -------------------------------------------------------------------------------- /advanced/page_cache.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 Page Cache 2 | *vanilla 的 Page Cache 实现了类似 Nginx 的 FastCGICache 或者 ProxyCache 的访问结果整体缓存,以 URI 的一定规则作为缓存的 KEY,属于内存型 Cache,存储位置可配置,默认存储在 OpenResty 共享字典(Share Dict)中,默认生成的项目中 Page Cache 为关闭状态* 3 | 4 | ###*Page Cache 相关配置* 5 | *Page Cache 相关的所有配置见项目的 config/application.lua 中, `Appconf.page_cache` 相关配置段,如下所示:* 6 | 7 | ```lua 8 | Appconf.page_cache = {} 9 | Appconf.page_cache.cache_on = true 10 | -- Appconf.page_cache.cache_handle = 'lru' 11 | Appconf.page_cache.no_cache_cookie = 'va-no-cache' 12 | Appconf.page_cache.no_cache_uris = { 13 | 'uris' 14 | } 15 | Appconf.page_cache.build_cache_key_without_args = {'rd'} 16 | ``` 17 | 18 | #####*配置释意* 19 | 20 | * cache_on 缓存开关,true 为开启 Page Cache,false 则为关闭 21 | * cache_handle 设置 Page Cache 的存储介质,目前支持 Memcache、Redis、resty.lrucache、OpenResty Share Dict,默认为 OpenResty Share Dict 22 | * no_cache_cookie 设置不缓存的 cookie KEY,Vanilla Page Cache 使用这个设置所指的 cookie KEY 来对某些特殊页面不缓存,默认当页面中有 KEY 为 `va-no-cache` 这个 COOKIE 的时候,当前页面不缓存 23 | * no_cache_uris 设置不缓存的 URI 列表,默认配置例如 http://app.com/uris 命中 `uris` 则,当前页面不缓存 24 | * build_cache_key_without_args 设置在缓存 KEY 中去除某些参数,比如某些 API 的版本号,或者随机数等,默认配置中的 `rd` 设置代表,当 URI 中有 rd 参数时,则生成的 Page Cache KEY 中清除这个参数 25 | 26 | *注:缓存的清理,只需要在请求的 URL 中,添加参数 `vapurge`* -------------------------------------------------------------------------------- /apis/bootstrap.md: -------------------------------------------------------------------------------- 1 | ##使用 Bootstrap 来做服务初始化 2 | *Vanilla 使用 Bootstrap 来做应用初始化的工作,用户可以在此对应用做一些配置(比如所使用的路由协议,使用何种视图引擎),对配置做一些初始化加载,初始化 WAF,初始化 Plugins 等操作,Vanilla 运行在 OpenResty content_by_lua\*这个 Phrase,使用 Bootstrap 可以很好的实现对请求的细粒度控制* 3 | 4 | ###*Bootstrap 即类 `application.bootstrap`* 5 | *Bootstrap 的实现其实是一个名为 `application.bootstrap` 的 Vanilla 类,实现了构造器初始化的属性只有一个(当前请求所使用的 dispatcher),我们只需要关注根据需求实现各种 init 方法即可,最后只要在 `boot_list` 方法返回的列表中的 init 方法都会被顺序执行* 6 | 7 | ```lua 8 | function Bootstrap:boot_list() 9 | return { 10 | -- Bootstrap.initWaf, 11 | -- Bootstrap.initErrorHandle, 12 | Bootstrap.initRoute, 13 | -- Bootstrap.initView, 14 | -- Bootstrap.initPlugin, 15 | } 16 | end 17 | 18 | function Bootstrap:__construct(dispatcher) 19 | self.dispatcher = dispatcher 20 | end 21 | ``` 22 | 23 | *上面的定义代表只有 `initRoute` 方法会被执行,而上面两个方法的实现我们并不需要关心和更改,只需要定义各种 init 方法,并更新 `boot_list` 返回的表元素即可,比如下面初始化路由协议的 `initRoute`* 24 | 25 | ```lua 26 | function Bootstrap:initRoute() 27 | local router = self.dispatcher:getRouter() 28 | local restful_route = restful:new(self.dispatcher:getRequest()) 29 | router:addRoute(restful_route, true) 30 | end 31 | ``` 32 | 33 | *注:可以通过 self.dispatcher 获取当前请求相关的详细信息,并进行相关控制* -------------------------------------------------------------------------------- /apis/buildin.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的內建变量和方法 2 | *为方便业务开发,Vanilla 提供了一些比较实用的內建方法和变量,这里我们说明如下,随着框架的更新,本页面会及时更新,欢迎随时关注。* 3 | 4 | ###*Vanilla 的內建变量* 5 | *Vanilla 的內建变量很多来自于 nginx.conf,其他则来自于 `ngx.var`,Vanilla 将这些变量都缓存在了 Registry 中* 6 | 7 | #### Registry 变量 8 | *Registry 是 Vanilla 中为了全局数据共享,及高效数据访问而封装的一个全局表,这里缓存了刻画当前请求比较全的数据,具体列表说明如下:* 9 | 10 | ```lua 11 | -- 以下数据以 "curl http://domain.org/?arg1=aa1&arg2=aa2" 访问为例进行说明 12 | Registry['APP_CONF'] -- 当前应用的配置数据,来自于(config/application.lua) 13 | Registry['sys_conf'] -- 当前应用的系统配置,来自于(sys/*路径,比如可以使用 Registry['sys_conf']['cache'] 获取 sys/cache 文件中关于 cache 的配置) 14 | Registry['REQ_URI'] -- 当前请求的 URI ,为 "/" 15 | Registry['REQ_ARGS'] -- 当前请求的参数字符串,即 Query_String,为 "arg1=aa1&arg2=aa2" 16 | Registry['REQ_ARGS_ARR'] -- 当前请求的参数列表,为一个 LUA 数组 17 | Registry['REQ_HEADERS'] -- 当前请求的请求头数组 18 | Registry['APP_NAME'] -- 应用名称 19 | Registry['APP_ROOT'] -- 应用所在根目录 20 | Registry['APP_HOST'] -- 当前请求的 HOST 信息 21 | Registry['APP_PORT'] -- 当前请求的 PORT 信息 22 | Registry['VANILLA_ROOT'] -- VANIALLA 框架的根目录 23 | Registry['VANILLA_VERSION'] -- 当前所使用的 VANILLA 版本号 24 | Registry['VANILLA_APPLICATION'] -- 'vanilla.v.application' LUA 包 25 | Registry['VANILLA_UTILS'] -- 'vanilla.v.libs.utils' LUA 包 26 | Registry['VANILLA_CACHE_LIB'] -- 'vanilla.v.cache' LUA 包 27 | Registry['VANILLA_COOKIE_LIB'] -- 'vanilla.v.libs.cookie' LUA 包 28 | Registry['APP_BOOTS'] -- 应用 'application.bootstrap' LUA 包 29 | Registry['APP_PAGE_CACHE_CONF'] -- 应用 Page Cache 相关配置 30 | ``` 31 | 32 | *注:上面很多全局变量是从 `ngx.var.` 获取来的结果缓存的,这样避免每次都请求 `ngx.var` 而减少这部分性能开销,并且其中有些信息比如 `APP_NAME`,`APP_ROOT` 等服务一经启动就不会更改,而像 `REQ_*` 相关的数据则是每次请求都不一样,好在一次请求可能对这部分数据会多次调用,所以将其缓存在 `Registry` 表中* 33 | 34 | ###*Vanilla 的內建函数* 35 | *Vanilla 有很多内建的函数,这些函数有些来自于 Vanilla 框架本身功能性的一些 LUA 包中,比如 `vanilla.v.controller`、`vanilla.v.request`、`vanilla.v.response` 等,另一些比如通用的方法,比如 `print_r`、 `page_cache` 和 `vanilla_init`,再有比如 Vanilla 定义的各种包加载函数,列表如下:* 36 | 37 | ```lua 38 | LoadLibrary -- 加载项目 library 路径下的 LUA 包 39 | LoadController -- 加载项目 controller 40 | LoadModel -- 加载项目 model 路径下的包,包括 DAO 和 Service 41 | LoadPlugin -- 加载项目 plugins 路径下所定义的插件 42 | LoadApplication -- 加载项目 application 路径下的 LUA 包 43 | LoadApp -- 加载项目根目录下面的 LUA 包 44 | LoadV -- 加载 Vanilla 框架相关的 LUA 包 45 | ``` 46 | 47 | *注:以上有些加载器功能重复,目的在于减短所传递参数的长度,比如加载 Index Controller, 使用 LoadController 方法是,只需要写 `LoadController('index'), 而如果使用方法 LoadApp 则应该写成 `LoadApp('application.controllers.index')`* 48 | 49 | #### 方法 `page_cache` 50 | *该方法调用 Vanilla 封装的页面缓存逻辑,详细内容参见[进阶/页缓存](../advanced/page_cache.md)* 51 | 52 | #### 单步调试方法 `print_r`、`sprint_r` 等 53 | *调试系列方法主要为了开发时能清晰方便的查看变量状态,记录开发日志等功能,详细内容参见[快速上手/如何调试](../quick_learning/debug.md)* 54 | 55 | #### 方法 `init_vanilla` 56 | *方法 `init_vanilla` 主要完成框架基础功能的初始化,比如 Registry 的初始化,各种 Loader 的定义,页面缓存的实现等,本方法默认在应用请求处理入口的第一句语句执行* 57 | -------------------------------------------------------------------------------- /apis/controller.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 controller 2 | *vanilla 的 controller 是业务处理的关键,基本的用法请参考 [快速开始](../quick_learning/add_controller.md)。* 3 | 4 | ###*关于 Controller* 5 | *Vanilla 的 Controller 可以是任何普通的 LUA 包,只不过导入的方法被用作处理请求的 Action。如下示例:* 6 | 7 | ```lua 8 | local IndexController = {} 9 | 10 | -- curl http://localhost:9110 11 | function IndexController:index() 12 | local view = self:getView() 13 | local p = {} 14 | p['vanilla'] = 'Welcome To Vanilla...' .. user_service:get() 15 | p['zhoujing'] = 'Power by Openresty' 16 | -- view:assign(p) 17 | do return view:render('index/index.html', p) end 18 | return view:display() 19 | end 20 | 21 | -- curl http://localhost:9110/index/action_b 22 | function IndexController:action_b() 23 | return 'index->action_b' 24 | end 25 | 26 | return IndexController 27 | ``` 28 | 29 | ###*更面向对象的 Controller* 30 | *Vanilla 支持使用 `Class` 方法来声明一个 Controller,实例如下:* 31 | 32 | ```lua 33 | local IndexController = Class('controllers.index') 34 | 35 | -- curl http://localhost:9110/index/action_b 36 | function IndexController:action_b() 37 | return 'index->action_b' 38 | end 39 | 40 | return IndexController 41 | ``` 42 | 43 | *这种情况下,可以定义 Controller 的构造器来对其进行初始化。示例如下:* 44 | 45 | ```lua 46 | local IndexController = Class('controllers.index') 47 | 48 | function IndexController:__construct() 49 | self.aa = aa({info='ppppp'}) 50 | end 51 | 52 | -- curl http://localhost:9110/index/action_b 53 | function IndexController:action_b() 54 | return 'index->action_b' 55 | end 56 | 57 | return IndexController 58 | ``` 59 | 60 | *甚至还可以声明一个 Controller 基类,处理某些通用的逻辑,相关的详细用法参见 Vanilla[面向对象](../advanced/oo.md) 相关章节。* 61 | 62 | 63 | ###*关于 Action 的返回值* 64 | 65 | *Vanilla 底层会将 Action 执行的结果,完全使用 `ngx.print` 进行输出,所以 Action 的返回值必须不能为空。而由于 Vanilla 的 Response 中,提供了给响应添加头尾的 `Response:appendBody` 和 `Response:prependBody` 方法,最终的结果会将这些部分合起来一起返回,所以 Action 的返回值要求如下:* 66 | 67 | * Action 返回值必须非空 68 | * Action 返回值可以为一维索引数组(不可以是多维 Hash 数组)或者字符串 -------------------------------------------------------------------------------- /apis/error.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的错误处理 2 | *Vanilla 的错误处理分为框架系统错误和应用错误两种类型,系统错误由框架控制,一般导致致命错误,直接抛出 500 内部错误,切不再往下执行,而应用错误则可以通过定义 `errorController` 来自定义处理* 3 | 4 | ###*Vanilla 应用错误* 5 | *Vanilla 提供了方便的错误处理方式,避免当代码运行报错后,页面只显示一个 500 错误的白页,没有详细报错信息,影响开发效率,Vanilla 的应用错误处理非常简单,在业务开发中,我们所关注的各个组件比如 DAO、Service、Controller、Action、Library 等都可能报错,Controller Action 作为 Vanilla 项目处理请求的执行体,一切业务组件的错误都可以通过一个统一的处理口径 `errorController` 来方便的处理。在业务组件开发过程中的错误,或者用户自定义的错误,都可以在 `errorController` 中得到捕获和处理,默认初始化的 demo 项目中,application/controllers/ 路径下,默认定义了一个 error.lua 文件,这就是前面所说的 `errorController`,下面我们具体来看看这段代码:* 6 | 7 | ```lua 8 | local ErrorController = {} 9 | local ngx_log = ngx.log 10 | local ngx_redirect = ngx.redirect 11 | local os_getenv = os.getenv 12 | 13 | 14 | function ErrorController:error() 15 | local env = os_getenv('VA_ENV') or 'development' 16 | if env == 'development' then 17 | local view = self:getView() 18 | view:assign(self.err) 19 | return view:display() 20 | else 21 | local helpers = require 'vanilla.v.libs.utils' 22 | ngx_log(ngx.ERR, helpers.sprint_r(self.err)) 23 | -- return ngx_redirect("http://sina.cn?vt=4", ngx.HTTP_MOVED_TEMPORARILY) 24 | return helpers.sprint_r(self.err) 25 | end 26 | end 27 | return ErrorController 28 | ``` 29 | 30 | *代码释意:(你只需要关注以下几点,即可随意,按需定义适合你的 errorController)* 31 | 32 | * 这是一个普通的 LUA 包,一个普通的 Vanilla Controller,唯一需要注意的一点就是需要实现一个 `error` 方法,注意方法名小写 33 | * 可以通过对运行环境的判断来,对不同的运行环境进行不同的错误处理,比如开发环境可能需要直接将错误打印到页面,而生产环境可能需要出错误页面等 34 | 35 | 36 | ###*Vanilla 框架系统错误(致命错误)* 37 | *当有些 Vanilla 项目所必须的配置或者关键步骤执行异常而影响项目往下运行的情况下,会抛出致命错误,并结束当前请求,目前有以下几种情况* 38 | 39 | ####*关键配置缺少* 40 | *项目未配置项目名 `name`,或者未指定项目根路径 `root`,Vanilla 有很多地方依赖项目名,比如缓存的 KEY 设置,项目的各类包加载依赖于项目根路径做全局加载,多 APP 支持也依赖与此。如果 config/application.lua 中缺少这两个配置,则会如下错误:* 41 | 42 | ```bash 43 | Sys Err: Please set app name and app root in config/application.lua like: 44 | 45 | Appconf.name = 'idevz.org' 46 | Appconf.app.root='/data1/VANILLA_ROOT/idevz.org/' 47 | ``` 48 | 49 | ####*bootstrap 报错* 50 | *Bootstrap 中的各种 init 方法并不是必须的,但是如果这部分方法定义后,执行错误,将影响整体项目的正常运行,所以 application/bootstrap.lua 中的运行报错也会报出系统致命错误,举例如下:* 51 | 52 | ```lua 53 | function Bootstrap:initRoute() 54 | local router = self.dispatcher:getRouter() 55 | local restful_route = restful:new(self.dispatcher:getRequest()) 56 | router:addRoute(restful_route, true) 57 | print_r('xx' .. false) 58 | end 59 | ``` 60 | 61 | *注:以上代码,最后一行操作试图将字符串与 bool 值 false 连接,会报出致命错误,如下:* 62 | 63 | ```bash 64 |
65 | "...g/idevz/code/www/vanilla/orcon/application/bootstrap.lua:18: attempt to concatenate a boolean value"
66 | ```
67 | 
68 | ####*dispatch 执行报错*
69 | *dispatch 属于框架的请求分发操作,请求分发执行出错直接导致致命错误,不过这个错误由框架自己处理,用户不需要关注*


--------------------------------------------------------------------------------
/apis/plugins.md:
--------------------------------------------------------------------------------
 1 | ##Vanilla 的插件体系
 2 | *为了减少运行占用的系统资源,使开发更简便,Vanilla 默认只运行在 content_by_lua 这个 phrase,但是为了支持业务开发有层次化的请求控制,Vanilla 实现了便捷的插件机制,提供了六个钩子,给请求的细粒度控制提供了可能。下面我们来看看如何使用*
 3 | 
 4 | ###*Vanilla Plugin 的简单使用*
 5 | *在 Vanilla 项目中使用插件是非常简单的,只需要在 application/plugins/ 路径下实现 Vanilla 的插件 LUA 包即可,插件包可以按需实现 6 个钩子的方法。默认生成的 demo 项目中自动生成了一个 admin plugin,见 application/plugins/admin.lua。六个钩子方法按需实现,空方法可去掉,如下所示:*
 6 | 
 7 | ```lua
 8 | local AdminPlugin = LoadV('vanilla.v.plugin'):new()
 9 | 
10 | function AdminPlugin:routerStartup(request, response)
11 |     print_r('
')
12 |     if request.method == 'GET' then
13 |         print_r('-----------' .. sprint_r(request.headers) .. '----------')
14 |     else
15 |         print_r(request.headers)
16 |     end
17 | end
18 | 
19 | return AdminPlugin
20 | ```
21 | 
22 | ####*Vanilla Plugin 的调用*
23 | *Vanilla Plugins 的调用非常简单,只需要在 application/bootstrap.lua 中实现 `initPlugin` 方法,并调用 `dispatcher` 的插件注册方法将插件注入项目( `self.dispatcher:registerPlugin(admin_plugin)`),即能在对应的时机执行相关钩子对应的方法*
24 | 
25 | ```lua
26 | local Bootstrap = Class('application.bootstrap')
27 | 
28 | function Bootstrap:initPlugin()
29 |     local admin_plugin = LoadPlugin('plugins.admin'):new()
30 |     self.dispatcher:registerPlugin(admin_plugin);
31 | end
32 | 
33 | function Bootstrap:boot_list()
34 |     return {
35 |         Bootstrap.initPlugin,
36 |     }
37 | end
38 | 
39 | function Bootstrap:__construct(dispatcher)
40 |     self.dispatcher = dispatcher
41 | end
42 | 
43 | return Bootstrap
44 | ```
45 | 
46 | ###*Vanilla 支持的插件钩子*
47 | *以下列出 Vanilla 支持的 6 中插件钩子*
48 | 
49 | ```lua
50 | function Plugin:routerStartup(request, response)			-- 开始路由
51 | function Plugin:routerShutdown(request, response)			-- 路由结束
52 | function Plugin:dispatchLoopStartup(request, response)		-- 开始请求分发
53 | function Plugin:preDispatch(request, response)				-- 预分发(载入相关的 controller)
54 | function Plugin:postDispatch(request, response)				-- 请求响应
55 | function Plugin:dispatchLoopShutdown(request, response)		-- 请求分发执行结束
56 | ```


--------------------------------------------------------------------------------
/apis/route.md:
--------------------------------------------------------------------------------
 1 | ##Vanilla 的路由体系
 2 | *Vanilla 实现的路由体系有一个路由器(`vanilla.v.router`)和若干路由协议构成(Vanilla 默认实现了 `vanilla.v.routes.simple` 和 `vanilla.v.routes.restful` 两种路由协议,默认使用 `simple` 路由来路由请求),请求处理的开始阶段,Vanilla 通过调用路由器协议栈中的各种路由协议,计算出处理当前请求的 `controller` 和 `action`,这就是 Vanilla 路由体系的职责所在。如果默认的两种路由协议不能满足你的 URI 路由需求,你可以参考我的一篇[《如何给Vanilla(OpenResty)添加一个路由协议》](https://my.oschina.net/idevz/blog/603657)的博文*
 3 | 
 4 | ###*Vanilla 路由器*
 5 | *Vanilla 的路由器 `vanilla.v.router` 是请求路由的基础,路由器提供了对路由协议的添加 `addRoute(route, only_one)`,删除 `removeRoute(route_name)`,获取路由列表 `getRoutes()` 等方法,用户可以调用这些方法来管理路由协议栈并使用路由器,不过用户不需要关心路由器的实现,而只需要关注路由协议的实现。*
 6 | 
 7 | ####*给路由器添加一条路由协议*
 8 | *路由器只有唯一一个 `vanilla.v.router`,但路由协议可以有多个,通过 `addRoute(route, only_one)` 方法的调用可以向路由协议栈添加一条路由协议,第二个参数为可选参数,当设置为 `true` 时,代表将清空路由协议栈,只使用当前添加的这条路由协议,因为 Vanilla 路由请求的方式是路由器根据路由协议栈中的路由协议挨条解析,直到找到匹配的 `controller` 和 `action` 为止,太多的路由协议栈可能影响路由性能。*
 9 | 
10 | ####*删除一条路由协议*
11 | *Vanilla 的每条路由协议都有 `route_name` 属性,删除时只需要调用 `removeRoute(route_name)`*
12 | 
13 | ####*获取当前所使用的路由协议*
14 | *Vanilla 支持获取当前请求所使用的路由协议,只需调用 `getCurrentRoute()` 方法,调用 `getCurrentRouteName()` 方法可以获取当前路由协议名*
15 | 
16 | ###*路由协议*
17 | *路由协议非常的简单,因为路由协议的关键功能在于为当前请求找到对应的 `controller` 和 `action`,核心在于根据当前请求实例 `request`,通过实现 `match` 方法,来获取结果,下面是根据 `vanilla.v.routes.simple` 路由协议提炼出来的路由协议简单骨架:*
18 | 
19 | ```lua
20 | local Simple = {}
21 | 
22 | function Simple:new(request)
23 |     local instance = {
24 |         route_name = 'vanilla.v.routes.simple',
25 |     	request = request
26 |     }
27 | 
28 |     setmetatable(instance, {
29 |         __index = self,
30 |         __tostring = function(self) return self.route_name end
31 |         })
32 |     return instance
33 | end
34 | 
35 | function Simple:match()
36 | end
37 | 
38 | return Simple
39 | ```
40 | 
41 | *注:我们需要关注以下两点*
42 | 
43 | * `route_name` 这是路由协议栈索引的关键,协议栈中的路由协议依靠 route_name 进行管理
44 | * `request` 是当前请求的实例,包含了当前请求携带的 URI,http_header 等数据,是请求路由的依据


--------------------------------------------------------------------------------
/apis/view.md:
--------------------------------------------------------------------------------
 1 | ##Vanilla 的视图引擎
 2 | *为去除模板运行时模板解析带来的不必要开销,从 vanilla-0.1.0.rc7 起 Vanilla 开始支持 OpenResty 官方的 Lemplate 模板引擎,下面将简要介绍 Vanilla 中 Lemplate 的用法,以及 Vanilla View 接口介绍*
 3 | 
 4 | ###*Vanilla 的视图渲染*
 5 | *Vanilla 在 `vanilla.v.dispatcher` 中导入了默认的模板引擎(`local View = LoadV 'vanilla.v.views.rtpl'`),但是可以在 Bootstrap 中实现 `initView` 来修改所使用的视图引擎。*
 6 | *而 Vanilla 的模板渲染,只需要在相应的 Action 中获取当前视图实例,注入数据,展示即可。下面就以 Lemplate 模板引擎为例,展示相关用法*
 7 | 
 8 | ####*首先在 Bootstrap 中实现 `initView` 方法,修改项目所使用的视图引擎*
 9 | 
10 | ```lua
11 | -- application/bootstrap.lua
12 | function Bootstrap:initView()
13 |     local view = LoadV('vanilla.v.views.lemplate'):new(self.dispatcher.application.config.view)
14 |     self.dispatcher:setView(view)
15 | end
16 | 
17 | -- boot_list 中打开 Bootstrap.initView 方法调用
18 | function Bootstrap:boot_list()
19 |     return {
20 |         -- Bootstrap.initWaf,
21 |         -- Bootstrap.initErrorHandle,
22 |         -- Bootstrap.initRoute,
23 |         Bootstrap.initView,
24 |         -- Bootstrap.initPlugin,
25 |     }
26 | end
27 | ```
28 | 
29 | ####*运行 `./va-{app_name}-service ltpl` 命令调用 `Lemplate` 编译你的 TT2 模板*
30 | 
31 | *下面是 TT2 模板示意*
32 | 
33 | ```html
34 | 
35 | 
36 | 
37 | 	
38 | 	[% title %]
39 | 
40 | 
41 | 
42 | [% FOREACH userinfo IN userlists %] 43 |

44 |

姓名:[% userinfo.name %] / 地址:[% userinfo.addr %]
45 |

46 | [% END %] 47 |
48 | 49 | 50 | ``` 51 | 52 | ####*在 Vanilla Action 中调用编译好的模板* 53 | 54 | ```lua 55 | function IndexController:index() 56 | local view = self:getView() 57 | local users = { 58 | {name='idevz', addr='yunnan'}, 59 | {name='vanilla', addr='beijing'}, 60 | } 61 | return view:assign({userlists=users, title = 'Vanilla-Lemplate'}) 62 | end 63 | ``` 64 | 65 | *注:* 66 | 67 | * `local view = self:getView()` 获取当前视图实例 68 | * `view:assign({userlists=users, title = 'Vanilla-Lemplate'})` 将数据注入视图 69 | 70 | *注:以上为 Lemplate 所使用的 TT2 模板实例,关于 Lemplate 的详细使用,可参考其详细[文档](https://github.com/openresty/lemplate)* -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /bootstrap.md: -------------------------------------------------------------------------------- 1 | ## Bootstrap 2 | *Vanilla服务运行前可以通过Bootstrap进行初始化操作,比如:装载相关的路由、插件、视图、错误处理甚至是Waf, 3 | 或者进行配置是初始化等.* 4 | 5 | *WAF配置* 6 | 7 | ###App配置 8 | #####*application.lua* 9 | #####*errors.lua* 10 | ###Nginx配置 11 | #####*nginx.lua* 12 | ###WAF配置 13 | #####*waf.lua* 14 | -------------------------------------------------------------------------------- /buildin.md: -------------------------------------------------------------------------------- 1 | ##内建类 2 | *香草/Vanilla的配置由以下三个部分组成.* 3 | - *App配置* 4 | - *Nginx配置* 5 | - *WAF配置* 6 | 7 | ###App配置 8 | #####*application.lua* 9 | #####*errors.lua* 10 | ###Nginx配置 11 | #####*nginx.lua* 12 | ###WAF配置 13 | #####*waf.lua* 14 | #####*waf.lua* 15 | #####*waf.lua* 16 | -------------------------------------------------------------------------------- /cconfig.md: -------------------------------------------------------------------------------- 1 | ##配置 2 | *香草/Vanilla的配置由以下三个部分组成.* 3 | - *App配置* 4 | - *Nginx配置* 5 | - *WAF配置* 6 | 7 | ###App配置 8 | #####*应用基础配置(config/application.lua)* 9 | 10 | ```lua 11 | Appconf.sysconf = { --系统预加载配置文件 12 | 'v_resource', 13 | } 14 | Appconf.name = 'app_name' --app名称,执行vanilla new命令时给定的应用名 15 | 16 | Appconf.route='vanilla.v.routes.simple' --路由器,指定URL路由方式,目的解析出需要执行的controller与action 17 | Appconf.bootstrap='application.bootstrap' --初始化bootstrap(用来对应用进行初始化操作) 18 | Appconf.app={} --app相关配置 19 | Appconf.app.root='./' --当前vanilla start命令执行路径 20 | 21 | Appconf.controller={} --当前app的controller相关配置 22 | Appconf.controller.path=Appconf.app.root .. 'application/controllers/' --controller文件所在路径(使用默认生成路径即可) 23 | 24 | Appconf.view={} --当前app的视图层相关配置 25 | Appconf.view.path=Appconf.app.root .. 'application/views/' --模板路径 26 | Appconf.view.suffix='.html' --模板后缀 27 | Appconf.view.auto_render=true --是否开启自动渲染 28 | ``` 29 | 30 | #####*应用基础配置的引用* 31 | 32 | ```lua 33 | -- 如上的配置,可以在代码中通过 Registry['APP_CONF'] 表来进行获取,比如获取 APP_NAME 34 | local app_name = Registry['APP_CONF']['name'] 35 | ``` 36 | 37 | #####*错误处理配置(config/errors.lua)* 38 | *根据errors.lua文件中实例,配置用户级别错误码.* 39 | 40 | ```lua 41 | local Errors = { 42 | [1000] = { status = 500, message = "Controller Err." }, 43 | } 44 | ``` 45 | 46 | #####*Restful 路由协议配置(config/restful.lua)* 47 | *根据 URI 需要来自定义路由协议的配置* 48 | 49 | ```lua 50 | local restful = { 51 | v1={}, 52 | v={} 53 | } 54 | 55 | restful.v.GET = { 56 | {pattern = '/', controller = 'index', action = 'index'}, 57 | {pattern = '/:category', controller = 'index', action = 'list'} 58 | } 59 | 60 | restful.v.POST = { 61 | {pattern = '/post', controller = 'index', action = 'post'}, 62 | } 63 | 64 | restful.v1.GET = { 65 | {pattern = '/api', controller = 'index', action = 'api_get'}, 66 | } 67 | 68 | return restful 69 | ``` 70 | 71 | 72 | 73 | #####*系统相关配置(sys/*)* 74 | *比如DB、MC等资源配置,系统相关的分机房配置等(在某些大公司,这部分配置又运维人员统一管理和下发),文件格式目前使用相对更运维友好的 ini 文件,开发中可以方便的在 Registry['sys_conf'] 中获取相关数据,如 `Registry['sys_conf']['cache']['lrucache']` 获取 lrucache 相关配置* 75 | 76 | #####*系统缓存相关配置 (sys/cache)* 77 | 78 | ```ini 79 | [shared_dict] 80 | dict=idevz 81 | exptime=100 82 | 83 | [memcached] 84 | instances=127.0.0.1:11211 127.0.0.1:11211 85 | exptime=60 86 | timeout=100 87 | poolsize=100 88 | idletimeout=10000 89 | 90 | [redis] 91 | instances=127.0.0.1:6379 127.0.0.1:6379 92 | exptime=60 93 | timeout=100 94 | poolsize=100 95 | idletimeout=10000 96 | 97 | [lrucache] 98 | items=200 99 | exptime=60 100 | useffi=false 101 | ``` 102 | 103 | * 目前这部分配置一般由 vanilla.v.libs.cache 来使用 104 | * 目前支持的配置项如 poolsize(连接池大小)、timeout(数据获取超时等) 105 | 106 | #####*系统缓存相关配置 (sys/v_resource)* 107 | 108 | ```ini 109 | [mc] 110 | conf=127.0.0.1:7348 127.0.0.1:11211 111 | 112 | [redis] 113 | conf=127.0.0.1:7348 127.0.0.1:7349 114 | 115 | [redisq] 116 | conf=127.0.0.1:7348 127.0.0.1:7349 117 | 118 | [db.user.write] 119 | host =127.0.0.1 120 | port =3306 121 | dbname =user.info 122 | user =idevz 123 | passwd =idevz 124 | 125 | [db.user.read] 126 | host =127.0.0.1 127 | port =3306 128 | dbname =user.info 129 | user =idevz 130 | passwd =idevz 131 | ``` 132 | 133 | * 对所使用的数据资源做配置 134 | * `Registry['sys_conf']['v_resource)']['db.user.write']['host']` 获取写库的 HOST 信息 135 | 136 | ###Nginx配置 137 | #####自动生成的 Nginx 配置文件 138 | *初始化项目的时候会在项目目录下(nginx_conf/)自动生成这个项目所对应的两套(分别对应开发和线上环境)配置文件,生成的两套配置文件中,每套都包含 nginx.conf 和 vhost 两个配置文件* 139 | 140 | #### 生产环境 141 | ###### va-nginx.conf 文件 142 | *va-nginx.conf 配置文件内容包含 nginx 配置主干(main、events、http 等重点配置段),包括用户、组的配置,工作进程等等通用配置,关键的还有 `lua_package_path`、`lua_package_cpath` 的配置,还有框架初始化文件(vanilla/framework/init.lua)的加载* 143 | 144 | ###### vhost/app_name.conf 文件 145 | *vhost/app_name.conf 文件是当前应用的相关配置,包括 APP_NAME、VANILLA_VERSION、$template_root、$va_cache_status 等全局变量的初始化,$document_root,Server_name 等的设置,还有关键的应用入口(content_by_lua_file),lua_shared_dict 等的设置,不过这些设置都是自动生成的,开发人员没有特殊需求的话,并不需要关注这些* 146 | 147 | #### 开发环境 148 | ###### va-nginx-development.conf 文件 149 | *va-nginx-development.conf 文件的内容跟开发环境类似,唯一的区别在于加载框架初始化文件(vanilla/framework/init.lua)的方式为 `init_by_lua_file`* 150 | 151 | ###### dev_vhost/app_name.conf 文件 152 | *默认的dev_vhost/app_name.conf 文件的配置同生产环境的配置基本一样,关键不同在于 `lua_code_cache` 的设置* 153 | 154 | *注:所以初始化项目后,首先需要执行 `sudo ./va-app_name-service initconf dev` 命令,就是为了将自动生成的配置文件部署到 OpenResty 默认的配置文件路径下,如果需要更新 va-nginx(-development).conf 则还需要在命令后面加上 `-f` 参数进行强行部署,每次如果需要修改配置,也只需修改这部分配置,然后执行 `initconf` 即可* 155 | 156 | #####*nginx.lua*( vanilla-0.1.0.rc5 后废弃此配置 ) 157 | *分为ngx_conf.common和ngx_conf.env两个部分,common是对Openresty指令集的配置如INIT_BY_LUA,可以是包或者文件(BY_LUA_FILE),env是环境的部分,包括了开发环境,测试环境和生产环境端口和缓存配置等控制.* 158 | 159 | ```lua 160 | ngx_conf.common = { 161 | INIT_BY_LUA = 'nginx.init', 162 | CONTENT_BY_LUA_FILE = './pub/index.lua' 163 | } 164 | ngx_conf.env = {} 165 | ngx_conf.env.development = { 166 | LUA_CODE_CACHE = false, 167 | PORT = 7200 168 | } 169 | ``` 170 | 171 | ###WAF配置 172 | #####*waf.lua* 173 | *包括WAF规则的配置,及各种规则参数的配置,相关使用方法详见[waf](https://github.com/loveshell/ngx_lua_waf)* 174 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/cover.jpg -------------------------------------------------------------------------------- /error.md: -------------------------------------------------------------------------------- 1 | ##异常处理 2 | *香草/Vanilla的配置由以下三个部分组成.* 3 | - *App配置* 4 | 5 | ###App配置 6 | #####*application.lua* 7 | #####*errors.lua* 8 | ###Nginx配置 9 | #####*nginx.lua* 10 | ###WAF配置 11 | #####*waf.lua* 12 | -------------------------------------------------------------------------------- /install/0_1_rc3.md: -------------------------------------------------------------------------------- 1 | ### *香草/Vanilla* 2 | *香草/Vanilla是一个基于Openresty实现的高性能Web应用开发框架.* 3 | 4 | ![Vanilla](http://m1.sinaimg.cn/maxwidth.300/m1.sinaimg.cn/120d7329960e19cf073f264751e8d959_2043_2241.png) 5 | 6 | ### *邮件列表* 7 | - vanilla-en 8 | - vanilla-devel 9 | - vanilla中文邮件列表 10 | 11 | ### *推荐始终使用最新版的Vanilla* 12 | *当前Vanilla最新版本0.1.0.rc7,支持命令:* 13 | 14 | - vanilla-0.1.0.rc7(*你没看错,自0.1.0.rc5起,vanilla的命令行和框架代码都带着版本号,方便多版本共存,也方便框架升级*) 15 | - v-console-0.1.0.rc7 16 | 17 | ### *安装* 18 | *目前Vanilla支持两种安装方式* 19 | 20 | - Make(推荐使用此种) 21 | - Luarocks(已有 OpenResty 环境 Luarocks 的安装可以参考[《基于 OpenResty 安装 Luarocks》](./or_luarocks.md)) 22 | 23 | #### *```make install```安装须知* 24 | Vanilla 支持的选项都提供了默认值,如果你的环境与默认值不一样,请configure时指定成你自己的。 25 | 26 | 特别注意选项```--openresty-path```,默认为```/usr/local/openresty```,请确保设置正确。 27 | 28 | 可以在源码目录下执行```configure --help```来查看安装选项的使用方法。 29 | 30 | 下面是一个简单的安装示例: 31 | ``` 32 | ./configure --prefix=/usr/local/vanilla --openresty-path=/usr/local/openresty 33 | 34 | make install (如果没有C模块【目前支持lua-filesystem】,则不需要make,直接make install) 35 | ``` 36 | #### *```luarocks install```安装须知* 37 | *可以使用luarocks安装vanilla,但是下面三点请注意* 38 | 1. Luarocks应该基于lua5.1.x的版本安装,因为其他版本Lua和Luajit的ABI存在兼容性问题。 39 | 2. Luarocks安装的Vanilla在nginx.conf文件的NGX_PATH变量不可用。 40 | 3. 请确保nginx命令可以直接运行(nginx命令在你的环境变量中) 41 | 42 | ### Vanilla 使用 43 | #### *Vanilla命令* 44 | *Vanilla 目前提供了两个命令 ```vanilla```,和 ```vanilla-console```* 45 | - ```vanilla```用来初始化应用骨架,停启服务(添加--trace参数可以看到执行的命令) 46 | - ```vanilla-console``` 是一个交互式命令行,主要提供一种方便学习Lua入门的工具,可以使用一些vanilla开发环境下的包,比如table输出的lprint_r方法。 47 | 48 | 命令行执行 ```vanilla```就能清晰看到 ```vanilla```命令提供的选项。 49 | 50 | ~~~ 51 | vanilla 52 | Vanilla v0.1.0-rc3, A MVC web framework for Lua powered by OpenResty. 53 | 54 | Usage: vanilla COMMAND [ARGS] [OPTIONS] 55 | 56 | The available vanilla commands are: 57 | new [name] Create a new Vanilla application 58 | start Starts the Vanilla server 59 | stop Stops the Vanilla server 60 | 61 | Options: 62 | --trace Shows additional logs 63 | ~~~ 64 | 65 | #### *创建应用* 66 | ``` 67 | vanilla new app_name 68 | cd app_name 69 | vanilla start [--trace] -- 默认运行在development环境 70 | 71 | ## 在linux的bash环境下: 72 | VA_ENV=production vanilla start [--trace] -- 运行在生产环境 73 | ## 在BSD等tcsh环境下: 74 | setenv VA_ENV production;vanilla start [--trace] -- 运行在生产环境 75 | ``` 76 | #### *代码目录结构* 77 | ``` 78 |  /Users/zj-git/app_name/ tree ./ 79 | ./ 80 | ├── application(应用代码主体目录) 81 | │   ├── bootstrap.lua(应用初始化 / 可选<以下未标可选为必选>) 82 | │   ├── controllers(应用业务代码主体目录) 83 | │   │   ├── error.lua(应用业务错误处理,处理本路径下相应业务报错) 84 | │   │   └── index.lua(hello world示例) 85 | │   ├── library(应用本地类包) 86 | │   ├── models(应用数据处理类) 87 | │   │   ├── dao(数据层业务处理) 88 | │   │   │   └── table.lua 89 | │   │   └── service(服务化业务处理,对DAO的再次封装) 90 | │   │   └── user.lua 91 | │   ├── nginx(*Openresty所封装Nginx请求处理各Phase) 92 | │   │   └── init.lua(*init_by_lua示例) 93 | │   ├── plugins(插件目录) 94 | │   └── views(视图层,与controllers一一对应) 95 | │   ├── error(错误模板) 96 | │   │   └── error.html 97 | │   └── index(index controller模板) 98 | │   └── index.html 99 | ├── config(应用配置目录) 100 | │   ├── application.lua(应用基础配置 / 路由器、初始化等设置) 101 | │   ├── errors.lua(应用错误信息配置) 102 | │   ├── nginx.conf(nginx配置文件模板) 103 | │   ├── nginx.lua(服务各种运行环境配置 / 是否开启lua_code_cache等) 104 | │   ├── waf-regs(应用防火墙规则配置目录) 105 | │   │   ├── args 106 | │   │   ├── cookie 107 | │   │   ├── post 108 | │   │   ├── url 109 | │   │   ├── user-agent 110 | │   │   └── whiteurl 111 | │   └── waf.lua(服务防火墙配置) 112 | ├── logs(日志目录) 113 | │   └── hack(攻击日志目录 / 保持可写权限) 114 | ├── pub(应用Nginx配置根路径) 115 | └── index.lua(应用请求入口) 116 | ``` 117 | #### *业务代码示例 IndexController* 118 | ``` 119 | local IndexController = {} 120 | 121 | function IndexController:index() 122 | local view = self:getView() 123 | local p = {} 124 | p['vanilla'] = 'Welcome To Vanilla...' 125 | p['zhoujing'] = 'Power by Openresty' 126 | view:assign(p) 127 | return view:display() 128 | end 129 | 130 | return IndexController 131 | ``` 132 | #### *模板示例 views/index/index.html* 133 | ``` 134 | 135 | 136 | 137 | 138 |

{{vanilla}}

{{zhoujing}}
139 | 140 | 141 | ``` 142 | 143 | ### 为什么需要Vanilla 144 | 回答这个问题,我们只需要看清楚Openresty和Vanilla各自做了什么即可。 145 | #### *Openresty* 146 | 147 | - 提供了处理HTTP请求的全套整体解决方案 148 | - 给Nginx模块开发开辟了一条全新的道路,我们可以使用Lua来处理Web请求 149 | - 形成了一个日趋完善的生态,这个生态涵盖了高性能Web服务方方面面 150 | 151 | #### *Vanilla* 152 | - 使复杂的Nginx配置对Web业务开发者更透明化 153 | - 开发者不再需要了解Openresty的实现细节,而更关注业务本身 154 | - 实现了Web开发常规的调试,错误处理,异常捕获 155 | - 实现了请求的完整处理流程和插件机制,支持路由协议、模板引擎的配置化 156 | - 整合、封装了一系列Web开发常用的工具集、类库(cookie、应用防火墙等) 157 | - 实现了自动化、配置化的Nginx指令集管理 158 | - 更合理的利用Openresty封装的8个处理请求Phase 159 | - 支持不同运行环境(开发、测试、上线)服务的自动化配置和运行管理 160 | - 功能使用方便易于扩展 161 | - 基于Openresty开发,具备Openresty一切优良特性 162 | 163 | ### 社区组织 164 | #### *QQ群&&微信公众号* 165 | - *Openresty/Vanilla 开发 1 群:205773855* 166 | - *Openresty/Vanilla 开发 2 群:419191655* 167 | - *Openresty 技术交流 1 群:34782325* 168 | - *Openresty 技术交流 2 群:481213820* 169 | - *Openresty 技术交流 3 群:124613000* 170 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 171 | 172 | ![vanilla](va_c.jpeg) 173 | 174 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /install/0_1_rc4.md: -------------------------------------------------------------------------------- 1 | ##香草/Vanilla 2 | *0_1_rc4 的安装使用与 0_1_rc3 没有本质区别,相关内容见 [0_1_rc3](0_1_rc3.md).* 3 | 4 | ![Vanilla](http://m1.sinaimg.cn/maxwidth.300/m1.sinaimg.cn/120d7329960e19cf073f264751e8d959_2043_2241.png) 5 | 6 | ### *邮件列表* 7 | - vanilla-en 8 | - vanilla-devel 9 | - vanilla中文邮件列表 10 | 11 | ### *推荐始终使用最新版的Vanilla* 12 | 13 | ### 社区组织 14 | #### *QQ群&&微信公众号* 15 | - *Openresty/Vanilla 开发 1 群:205773855* 16 | - *Openresty/Vanilla 开发 2 群:419191655* 17 | - *Openresty 技术交流 1 群:34782325* 18 | - *Openresty 技术交流 2 群:481213820* 19 | - *Openresty 技术交流 3 群:124613000* 20 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 21 | 22 | ![vanilla](va_c.jpeg) 23 | 24 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /install/0_1_rc5.md: -------------------------------------------------------------------------------- 1 | ### *安装* 2 | 3 | #### *通过 ./setup-framework 脚本安装 Vanilla* 4 | 5 | *`./setup-framework` 脚本是对 `make install` 后面安装方式一个自动化封装,仅需要指定 OpenResty 的安装路径,即可简单安装 Vanilla* 6 | 7 | ``` 8 | ./setup-framework -h 9 | Usage: ./setup-framework 10 | -h show this help info 11 | -v VANILLA_PROJ_ROOT, vanilla project root, will contain vanilla framework and apps 12 | -o OPENRESTY_ROOT, openresty install path(openresty root) 13 | ``` 14 | 15 | `./setup-framework` 脚本参数选项说明: 16 | 17 | - -v : 指定 Vanilla 项目的根目录,此选项默认为 `/data/vanilla`,默认则将 Vanilla 安装到 `/data/vanilla/framework/0_1_0_rc5/vanilla/` 目录下。 18 | 19 | - -o : 指定 OpenResty 的安装目录, 此选项默认为 `/usr/local/openresty`, 如果你的 OpenResty 安装路径与此不同,则需要指定为正真的 OpenResty 安装目录。 20 | 21 | 安装目录结构如下: 22 | 23 | ``` 24 | tree /data/vanilla -L 2 25 | /data/vanilla 26 | ├── framework 27 | │   ├── 0_1_0_rc5 28 | │   └── 0_1_0_rc5.old_2016_04_12_11_04_18 # 重复安装则会将之前的老版本按照时间自动备份 29 | ``` 30 | 31 | #### *通过 ```make install``` 安装 Vanilla* 32 | 33 | Vanilla 支持的选项都提供了默认值,如果你的环境与默认值不一样,请configure时指定成你自己的。 34 | 35 | 特别注意选项```--openresty-path```,默认为```/usr/local/openresty```,请确保设置正确。 36 | 37 | 可以在源码目录下执行```configure --help```来查看安装选项的使用方法。 38 | 39 | 下面是一个简单的安装示例: 40 | 41 | ``` 42 | ./configure --prefix=/usr/local/vanilla --openresty-path=/usr/local/openresty 43 | 44 | make install (不需要make,直接make install) 45 | ``` 46 | 47 | 48 | ### Vanilla 使用 49 | 50 | ####*Vanilla-V0.1.0-rc4.1 及其之前版本的配置和使用,请查阅[README-zh-V0.1.0-rc4.1.md](README/README-zh-V0.1.0-rc4.1.md)* 51 | 52 | #### *Vanilla命令* 53 | 54 | *Vanilla-V0.1.0-rc5 目前依旧提供两个命令, 但是 rc5 以后提供的命令与安装的框架代码一样,都自动携带版本号,```vanilla-0.1.0.rc5```,和 ```v-console-0.1.0.rc5``` 这样做的好处在于方便多版本共存以及 Vanilla 的无痛升级* 55 | - ```vanilla-0.1.0.rc5```用来初始化应用骨架,而 `vanilla-0.1.0.rc5` 之后,服务的停启不再通过 `vanilla-0.1.0.rc5` 命令管理,而是通过项目路径下面的 `va-appname-service` 脚本进行管理,使用细节见后面说明。 56 | - ```v-console-0.1.0.rc5``` 是一个交互式命令行,主要提供一种方便学习Lua入门的工具,可以使用一些 vanilla 开发环境下的包,比如table输出的 lprint_r 方法等。 57 | 58 | #### *创建应用* 59 | ``` 60 | vanilla-0.1.0.rc5 new app_full_path #使用 vanilla-0.1.0.rc5 命令 自动生成应用骨架,注意这里需要传递应用的全路径,而不只是一个APP_NAME 61 | chmod +x app_full_path/va-appname-service #给生成的项目骨架根目录下面的 va-appname-service 脚本添加执行权限 62 | app_full_path/va-appname-service initconf [dev] #初始化应用的nginx配置文件,此文件基于 app_full_path/nginx_conf 下面的配置文件生成,如果有特殊选项需要配置,可以先修改 app_full_path/nginx_conf 下面的配置文件,再进行 initconf 操作,[dev] 参数为可选项, 加上则表示执行开发环境相关操作,不加则默认为生产环境 63 | app_full_path/va-appname-service start [dev] #启动生成的服务,即可通过http://localhost访问服务,[dev] 参数如上。 64 | ``` 65 | 上面创建应用的过程也可以通过脚本 `./setup-vanilal-demoapp` 简单自动完成: 66 | ``` 67 | ./setup-vanilal-demoapp -h 68 | Usage: ./setup-vanilal-demoapp -h show this help info 69 | -a VANILLA_APP_ROOT, app absolute path(which path to init app) 70 | -u VANILLA_APP_USER, user to run app 71 | -g VANILLA_APP_GROUP, user group to run app 72 | -e VANILLA_RUNNING_ENV, app running environment 73 | ``` 74 | `./setup-vanilal-demoapp` 脚本参数选项说明: 75 | - -a : 指定初始化应用的全路径(绝对路径),默认为 /data/vanilla/vademo 76 | - -u : 指定运行服务的用户名,默认为 idevz 77 | - -g : 指定运行服务的用户组,默认为 sina 78 | - -e : 指定运行服务的环境,默认为'' 指生产环境 79 | 80 | 安装目录结构如下: 81 | 82 | ``` 83 | tree /data/vanilla/ -L 1 84 | /data/vanilla/ 85 | ├── framework # vanilla 框架安装目录 86 | ├── vademo # 应用初始化目录 87 | └── vademo.old_2016_04_12_11_04_26 # 重复安装后会将之前版本按照时间进行备份 88 | ``` 89 | 90 | #### *应用配置初始化与服务管理* 91 | *通过脚本 /data/vanilla/vademo/va-vademo-service 管理 vademo 服务* 92 | 93 | ``` 94 | /data/vanilla/vademo/va-vademo-service -h 95 | Usage: ./va-ok-service {start|stop|restart|reload|force-reload|confinit[-f]|configtest} [dev] #dev 指定了运行的环境,不加 dev 则默认为生产环境。 96 | ``` 97 | 98 | 注意:* 如果没有使用 ./setup-vanilal-demoapp 脚本,而是手动 new 的 app, 则在启动服务之前需要先运行 /data/vanilla/vademo/va-vademo-service initconf [dev] 对相应环境的 nginx 配置文件进行初始化。 * 99 | 100 | ##工程化的vanilla-0.1.0.rc5 101 | 102 | *vanilla-0.1.0.rc5是vanilla-0.1.0.rc4在新浪移动全线推广过程中针对一些工程化部署问题改进版本,可以肯定的一点vanilla-0.1.0.rc4在功能、扩展性、使用方面表现良好,非常适合移动业务的场景,更不止于API,但是在集群部署、多App部署、Vanilla框架升级等方面vanilla-0.1.0.rc4存在短板,而vanilla-0.1.0.rc5极大程度的弥补了这些短板。* 103 | 104 | ### *推荐始终使用最新版的Vanilla* 105 | *当前Vanilla最新版本0.1.0.rc5,支持命令:* 106 | 107 | - vanilla-0.1.0.rc5(*你没看错,自0.1.0.rc5起,vanilla的命令行和框架代码都带着版本号,方便多版本共存,也方便框架升级*) 108 | - v-console-0.1.0.rc5 109 | 110 | ##如何从vanilla-0.1.0.rc4到vanilla-0.1.0.rc5 111 | 112 | ### *升级步骤* 113 | 114 | #### 1.安装最新的 vanilla-0.1.0.rc5 115 | 116 | ``` bash 117 | $ wget https://github.com/idevz/vanilla/archive/v0.1.0-rc5.0.tar.gz 118 | $ tar zxf v0.1.0-rc5.0.tar.gz 119 | $ cd vanilla-0.1.0.rc5 120 | $ ./setup-framework -v $VANILLA_PROJ_ROOT -o $OPENRESTY_ROOT #$VANILLA_PROJ_ROOT 为给 Vanilla 指定的安装目录, $OPENRESTY_ROOT 是当前 OpenResty 的安装目录 121 | ``` 122 | 123 | #### 2.基于新的 Vanilla(vanilla-0.1.0.rc5) 初始化新版的 vatest 项目: 124 | 125 | ``` bash 126 | $ sudo vanilla-0.1.0.rc5 new $VANILLA_APP_ROOT #$VANILLA_APP_ROOT 为新版 vatest 项目全路径 127 | ``` 128 | 129 | #### 3.将新项目中的以下目录及文件直接覆盖至老版 vatest 的相关位置: 130 | - pub/index.lua 文件($VANILLA_APP_ROOT/pub/index.lua)直接覆盖 131 | - va-vasina-service 脚本($VANILLA_APP_ROOT/va-vasina-service)直接复制,因为老版没有这个文件 132 | - 注意确认脚本中 $OPENRESTY_NGINX_ROOT 的路径 133 | - 注意确认脚本中 $VA_APP_PATH 的路径是否为项目的根路径 134 | - nginx_conf 目录($VANILLA_APP_ROOT/nginx_conf)直接复制,因为老版没有这个目录 135 | - application/bootstrap.lua 文件($VANILLA_APP_ROOT/application/bootstrap.lua)将老项目 bootstrap 中的相关 init* 方法拷贝到新的 bootstrap.lua 中,并用新的 bootstrap.lua 覆盖老版的 bootstrap.lua 文件 136 | - 修改 $VANILLA_APP_ROOT/nginx_conf 中的 nginx 配置文件, 确保其中各种目录正确 137 | - 确保 $VANILLA_APP_ROOT/nginx_conf/va-nginx{-development}.conf 文件中 lua_package_{c}path 中, 全路径的 Vanilla 框架目录正确 138 | - 确保 $VANILLA_APP_ROOT/nginx_conf/{dev_}vhost/vasina.conf 文件中 Server 段的 `root` 配置为项目根目录, `require` 方法中 `local VANILLA_ROOT` 为框架根路径 139 | 140 | 141 | #### 4.使用 $VANILLA_APP_ROOT/va-vasina-service 脚本管理服务: 142 | 1. 给 $VANILLA_APP_ROOT/va-vasina-service 脚本添加可执行权限 `chmod +x $VANILLA_APP_ROOT/va-vasina-service` 143 | 2. 初始化 nginx 配置 `$VANILLA_APP_ROOT/va-vasina-service initconf [dev]` 144 | 3. 启动服务 `$VANILLA_APP_ROOT/va-vasina-service start [dev]` 145 | 146 | 注: 添加 `dev` 参数,则管理 development 环境的服务, 默认为 production 生产环境服务 147 | 148 | 149 | 150 | ### 社区组织 151 | #### *QQ群&&微信公众号* 152 | - *Openresty/Vanilla 开发 1 群:205773855* 153 | - *Openresty/Vanilla 开发 2 群:419191655* 154 | - *Openresty 技术交流 1 群:34782325* 155 | - *Openresty 技术交流 2 群:481213820* 156 | - *Openresty 技术交流 3 群:124613000* 157 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 158 | 159 | ![vanilla](va_c.jpeg) 160 | 161 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /install/0_1_rc6.md: -------------------------------------------------------------------------------- 1 | ### *安装* 2 | 3 | *vanilla-0-1-rc6 的安装与应用初始化同 [vanilla-0-1-rc5](0_1_rc5.md) 的方式相同, 详情请[点击](0_1_rc5.md) * 4 | 5 | 6 | 7 | ### 社区组织 8 | #### *QQ群&&微信公众号* 9 | - *Openresty/Vanilla 开发 1 群:205773855* 10 | - *Openresty/Vanilla 开发 2 群:419191655* 11 | - *Openresty 技术交流 1 群:34782325* 12 | - *Openresty 技术交流 2 群:481213820* 13 | - *Openresty 技术交流 3 群:124613000* 14 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 15 | 16 | ![vanilla](va_c.jpeg) 17 | 18 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /install/0_1_rc7.md: -------------------------------------------------------------------------------- 1 | ### *安装* 2 | 3 | *vanilla-0-1-rc7 的安装与应用初始化同 [vanilla-0-1-rc5](0_1_rc5.md) 的方式相同, 详情请[点击](0_1_rc5.md) * 4 | 5 | 6 | 7 | ### 变更 8 | #### *Add* 9 | - *Add lemplate 模板引擎* 10 | - *Add dynamic dns for lib.http* -------------------------------------------------------------------------------- /install/or_luarocks.md: -------------------------------------------------------------------------------- 1 | ### *基于 OpenResty 安装 Luarocks* 2 | 3 | *基于 OpenResty 来安装 其实意在基于 OpenResty 自带的 Luajit 来安装 Luarocks, Luarocks 安装时需要指定 lua 目录和 lua 的 include 目录,而 OpenResty 自身带有的 Luajit 就包含所需的 Lua 解释器和头文件。* 4 | *只不过 Luarocks 安装需要的是 Lua 而不是 Luajit,这就是关键的一步* 5 | 6 | ```bash 7 | # 我本机的 OpenResty 安装路径为 /usr/local/openresty-1.11.2.1/ 8 | # OpenResty 本身带的 Lua 解释器 Luajit 在 /usr/local/openresty-1.11.2.1/luajit/bin/ 路径 9 | # OpenResty 本身带的 Lua 相关头文件 include 在 /usr/local/openresty-1.11.2.1/luajit/include/ 路径 10 | # 我们需要做的就是建一个软连接,给 Luarocks 使用 11 | 12 | cd /usr/local/openresty-1.11.2.1/luajit/bin 13 | sudo ln -sf luajit-2.1.0-beta2 lua 14 | 15 | cd /usr/local/openresty-1.11.2.1/luajit/include 16 | sudo ln -sf luajit-2.1 lua5.1 17 | ``` 18 | 19 | *经过以上几步的准备工作,就可以进入正常的安装步骤,演示如下:* 20 | 21 | ```bash 22 | ./configure --with-lua-bin=/usr/local/openresty-1.11.2.1/luajit/bin --with-lua-include=/usr/local/openresty-1.11.2.1/luajit/include --prefix=/usr/local/luarocks-2.4.1 23 | sudo make build 24 | sudo make install 25 | ``` 26 | 27 | *安装完毕后,只需要将 Luarocks 安装路径的 bin 目录(/usr/local/luarocks-2.4.1/bin)加到 PATH 环境变量下,即可使用 `luarocks` 命令来管理标准 Lua 包,使用 Luarocks 安装的包将保存在 Luarocks 安装的 share 目录,而可执行文件(比如 Vanilla 的可执行命令 vanilla 和 v-console)都在 luarocks 命令同级目录。* -------------------------------------------------------------------------------- /install/va_c.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/install/va_c.jpeg -------------------------------------------------------------------------------- /intro/index_structure.md: -------------------------------------------------------------------------------- 1 | ##目录结构 2 | 3 | 4 | ###Vanilla-0.1.0.rc5推荐的目录结构 5 | 6 | *vanilla-0.1.0.rc5是对vanilla-0.1.0.rc4工程化的改进版,主要有以下2点推荐:* 7 | 8 | #### Vanilla_Root(框架和App都放到这个路径下) 9 | Vanilla相关的框架和App放到统一的一个目录(Vanilla_Root)下,比如我的是`/Users/zhoujing/vanilla`(方便管理,另外也告诉你Vanilla就是一个框架,放在哪儿都可以使用) 10 | 11 | ![vanilla root](vanilla_root.png) 12 | 13 | #### 框架与App 14 | 将Vanilla安装到`{Vanilla_Root}/framework`下,并使用全路径新建App:`vanilla new {Vanilla_Root}/va_app_demo` 15 | 16 | 框架的目录结构如下 17 | 18 | ![vanilla framework](vanilla_framework.png) 19 | 20 | Vanilla App的目录结构如下 21 | ![vanilla demo](vanilla_demo.png) 22 | 23 | ###0.1.0.rc4之前版本的目录说明 24 | 之前的vanilla默认安装在`/usr/local/vanilla`给大家传递了一个不好的信号,好像vanilla是一个服务,其实vanilla仅仅是一个MVC框架 25 | 26 | #### *vanilla新建的App代码目录结构及说明* 27 | ``` 28 |  /Users/zj-git/app_name/ tree ./ 29 | ./ 30 | ├── application(应用代码主体目录) 31 | │   ├── bootstrap.lua(应用初始化 / 可选<以下未标可选为必选>) 32 | │   ├── controllers(应用业务代码主体目录) 33 | │   │   ├── error.lua(应用业务错误处理,处理本路径下相应业务报错) 34 | │   │   └── index.lua(hello world示例) 35 | │   ├── library(应用本地类包) 36 | │   ├── models(应用数据处理类) 37 | │   │   ├── dao(数据层业务处理) 38 | │   │   │   └── table.lua 39 | │   │   └── service(服务化业务处理,对DAO的再次封装) 40 | │   │   └── user.lua 41 | │   ├── nginx(*Openresty所封装Nginx请求处理各Phase) 42 | │   │   └── init.lua(*init_by_lua示例) 43 | │   ├── plugins(插件目录) 44 | │   └── views(视图层,与controllers一一对应) 45 | │   ├── error(错误模板) 46 | │   │   └── error.html 47 | │   └── index(index controller模板) 48 | │   └── index.html 49 | ├── config(应用配置目录) 50 | │   ├── application.lua(应用基础配置 / 路由器、初始化等设置) 51 | │   ├── errors.lua(应用错误信息配置) 52 | │   ├── nginx.conf(nginx配置文件模板) 53 | │   ├── nginx.lua(服务各种运行环境配置 / 是否开启lua_code_cache等) 54 | │   ├── waf-regs(应用防火墙规则配置目录) 55 | │   │   ├── args 56 | │   │   ├── cookie 57 | │   │   ├── post 58 | │   │   ├── url 59 | │   │   ├── user-agent 60 | │   │   └── whiteurl 61 | │   └── waf.lua(服务防火墙配置) 62 | ├── logs(日志目录) 63 | │   └── hack(攻击日志目录 / 保持可写权限) 64 | ├── pub(应用Nginx配置根路径) 65 | └── index.lua(应用请求入口) 66 | ``` 67 | 68 | ### 社区组织 69 | #### *QQ群&&微信公众号* 70 | - *Openresty/Vanilla 开发 1 群:205773855* 71 | - *Openresty/Vanilla 开发 2 群:419191655* 72 | - *Openresty 技术交流 1 群:34782325* 73 | - *Openresty 技术交流 2 群:481213820* 74 | - *Openresty 技术交流 3 群:124613000* 75 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 76 | 77 | ![vanilla](va_c.jpeg) 78 | 79 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /intro/overview.md: -------------------------------------------------------------------------------- 1 | ##框架说明 2 | 香草/vanilla 的实现大致分为以下三个部分,本手册将会分别进行详述。 3 | 1. 系统层面关于Nginx指令集的封装、应用防火墙的实现等(vanilla/sys) 4 | 2. 框架层面关于请求处理的各种类包封装(vanilla/v) 5 | 3. 框架单元测试相关封装(vanilla/spec) 6 | 7 | ###系统层面(Vanilla关于Nginx控制的抽象和封装/vanilla/sys) 8 | ``` 9 | ├── vanilla 10 | │   ├── sys 11 | │   │   ├── application.lua(生成项目骨架) 12 | │   │   ├── config.lua(项目系统环境配置) 13 | │   │   ├── nginx 14 | │   │   │   ├── config.lua(Nginx配置文件解析,包括框架和应用两部分Nginx配置的合并) 15 | │   │   │   ├── directive.lua(Nginx配置指令封装) 16 | │   │   │   └── handle.lua(Nginx服务管理,start、stop) 17 | │   │   ├── vanilla.lua(Vanilla Nginx服务管理/启动,关闭等配置自动生成和销毁) 18 | │   │   └── waf 19 | │   │   ├── acc.lua(应用防火墙实现) 20 | │   │   └── config.lua(应用防火墙配置) 21 | ``` 22 | 23 | ###框架层面(Vanilla对Nginx请求的处理/vanilla/v) 24 | ``` 25 | ├── vanilla 26 | │   └── v 27 | │   ├── application.lua(application封装,标记一个应用) 28 | │   ├── bootstrap.lua(application初始化) 29 | │   ├── controller.lua(vanilla业务处理封装) 30 | │   ├── dispatcher.lua(vanilla请求处理分发器) 31 | │   ├── error.lua(vanilla系统错误实现) 32 | │   ├── libs(Web开发类包) 33 | │   │   ├── cookie.lua 34 | │   │   ├── http.lua 35 | │   │   ├── logs.lua 36 | │   │   ├── session.lua 37 | │   │   ├── shcache.lua 38 | │   │   └── utils.lua 39 | │   ├── plugin.lua(vanilla插件实现) 40 | │   ├── registry.lua(vanilla数据寄存器) 41 | │   ├── request.lua(vanilla请求封装) 42 | │   ├── response.lua(vanilla响应封装) 43 | │   ├── routes(vanilla实现的路由协议簇,目前仅支持简单路由,路由协议实现了URL到controller、action的规则化映射) 44 | │   │   └── simple.lua(简单路由) 45 | │   ├── view.lua(vanilla视图层) 46 | │   └── views(vanilla支持的模板引擎) 47 | │   └── rtpl.lua(vanilla目前默认的模板引擎resty.template) 48 | ``` 49 | 50 | ###单元测试 51 | vanilla使用busted作为单元测试框架 52 | #####*[Busted](http://olivinelabs.com/busted/)* 53 | ######add 54 | 55 | ### 社区组织 56 | #### *QQ群&&微信公众号* 57 | - *Openresty/Vanilla 开发 1 群:205773855* 58 | - *Openresty/Vanilla 开发 2 群:419191655* 59 | - *Openresty 技术交流 1 群:34782325* 60 | - *Openresty 技术交流 2 群:481213820* 61 | - *Openresty 技术交流 3 群:124613000* 62 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 63 | 64 | ![vanilla](va_c.jpeg) 65 | 66 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /intro/va_c.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/intro/va_c.jpeg -------------------------------------------------------------------------------- /intro/vanilla_start.md: -------------------------------------------------------------------------------- 1 | ##源起 2 | 3 | ###第一次邂逅 4 | 5 | 我第一次接触Openresty是2011年,当时我作为一个刚入行一年的新人在凤凰网(ifeng.com)负责论坛平台的开发维护工作,我一直梦想着能做一个大并发、高性能的系统,由于自己做PHP出身,当时使用更多的是Nginx、PHP-fpm,Nginx作为请求代理将接受到的请求转发到PHP-fpm的9000端口作为实际的业务处理。有次同事技术分享提到了Openresty,一个请求过来不再需要代理,而是一个Nginx的HTTP模块(ngx_http_lua)直接处理,Nginx本身以高性能、大并发著称,抛弃了繁重的PHP-fpm,我相信这肯定是我一直寻找的东西。无奈当时被业务绑架,自己服务端开发经验不足,只能把Openresty当成玩具,写写hello world,Ab压压随便就过万的QPS,聊以自慰,但是心里一直惦记着Openresty。 6 | 7 | ###念念不忘 8 | 2012年我离开凤凰,到了新浪无线,负责公司手机端页面的后端开发和维护,从WML,3G,HTML5,APP一路走来,我发现手机端的后端开发与PC端有本质的区别,手机端越来越多的依赖接口,各种异步化请求,手机端页面本身结构简单,文档体积小,而公司业务每天处理几十亿的请求,服务器资源有限,需要的就是高性能、大并发的后端服务,不论是页面还是接口都是如此,2012年到2015年3年的时间里我一直在试图在团队推进Openresty改造,从消灭全线的Apache服务器开始,到目前的业务框架的开发、推广,我一直都在追问自己,真的需要Openresty吗? 9 | 10 | 至少到目前为止基于自己对技术的学习和经验的积累,这个答案还是出奇的肯定:Openresty是最适合我们当前业务的。 11 | 12 | ###为什么需要Vanilla 13 | 至于有了Openresty为什么还需要另一个开发框架呢?首先熟悉Openresty的同学都知道```Openresty=Nginx+ngx_http_lua+Luajit```而对于大多数做业务开发的同学来说,Nginx、ngx_http_lua等各种模块对他们而言是陌生的,再就是Openresty提供了底层使用Lua处理HTTP请求的机制,但是并没有对WEB开发做太多的封装。对于长期从事业务开发的同学无法在Openresty中找到业务快速开发的支持,比如报错、调试、工具库、系统化、规范化的请求处理流程等等,为了让这些同学包括我自己能更快更深入的了解、使用和推广Openresty,我开发了这个框架Vanilla。它的名字承载了我对这个项目的愿景,希望Vanilla能像一簇淡然、安静、默默开放在开源社区的香草,为开源社区,为Openresty世界出一份自己的力量,也希望能有更多的人加入到开源工作中来,一起成长。 14 | 15 | ###感谢生命中的你们 16 | 这些年自己一直在各种技术社区,邮件组,各种分享活动中不断学习成长,以春哥(agentzh)为代表的Openresty社区给我的感触最为深刻,那里是一群默默进取的人,春哥以自己儒雅的个人魅力以及无私奉献的开源精神鼓舞着无数的开发者,大家聚在一起讨论、学习、共享、支持,我个人的成长离不开包括Openresty社区在内的整个开源世界,我很庆幸能遇到这么多志同道合的同学,在此深表感谢。 17 | 18 | ### 社区组织 19 | #### *QQ群&&微信公众号* 20 | - *Openresty/Vanilla 开发 1 群:205773855* 21 | - *Openresty/Vanilla 开发 2 群:419191655* 22 | - *Openresty 技术交流 1 群:34782325* 23 | - *Openresty 技术交流 2 群:481213820* 24 | - *Openresty 技术交流 3 群:124613000* 25 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 26 | 27 | ![vanilla](va_c.jpeg) 28 | 29 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /libs/cookie.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 中使用 Cookie 2 | *Vanilla 中封装了 `vanilla.v.libs.cookie` 包,源至 [`lua-resty-cookie`](https://github.com/cloudflare/lua-resty-cookie),提供了简单的 `get`、`set`、`getAll` 等方法来控制 Cookie,下面具体使用举例如下:* 3 | 4 | ###*vanilla.v.libs.cookie 包使用* 5 | 6 | *一例胜千言:* 7 | 8 | ```lua 9 | local IndexController = {} 10 | 11 | -- 载入 vanilla.v.libs.cookie 包 12 | local vcookie_lib = LoadV('vanilla.v.libs.cookie') 13 | 14 | function IndexController:index() 15 | 16 | -- 实例化 vanilla.v.libs.cookie 类 17 | local cookie = vcookie_lib() 18 | 19 | -- 调用 set 方法,设置 cookie 20 | cookie:set('idevz', 'kkkk', {expires=1000}) 21 | cookie:set('idevz_api', 'kkkk', {expires=1000,path='/'}) 22 | 23 | -- 调用 getAll 方法,获取所有 cookie,也可以调用 get 获取单个cookie 24 | print_r(cookie:getAll()) 25 | do return '' end 26 | end 27 | 28 | return IndexController 29 | ``` 30 | 31 | *注:* 32 | 33 | *`vanilla.v.libs.cookie` 支持以下 cookie 选项* 34 | 35 | ```lua 36 | path 37 | domain 38 | max_age 39 | secure 40 | httponly 41 | samesite 42 | extension 43 | ``` 44 | -------------------------------------------------------------------------------- /openresty/or_doc.md: -------------------------------------------------------------------------------- 1 | # OR文档精炼 2 | 3 | *感谢春哥给我们带来这么好的平台,在这里希望能通读 OR 文档,把自己的理解记录下来,并与时俱进的更新* 4 | 5 | ## 描述 / Description 6 | 7 | `lua-nginx-module` 模块通过标准的 Lua 5.1 解释器,或者 LuaJIT 2.0/2.1 在 Nginx 运行环境中嵌入 Lua,并利用 Nginx 的子请求,允许在 Nginx 的时间模块中集成强大的 Lua 线程(Lua 协程)。 8 | 9 | 与 Apache 的 `mod_lua` 和 Lighttpd 的 `mod_magnet` 不同的是,只要使用 `lua-nginx-module` 模块为 Lua 提供的 Nginx API 来处理上游服务的请求,诸如 MySQL、PostgreSQL、Memcached、Redis 或者上游的 HTTP Web 服务,网络传输都是 100% 非阻塞的。 10 | 11 | 至少下面列举的这些 Lua 包,和 Nginx 模块可以与 `ngx_lua` 模块完美结合使用: 12 | 13 | -------------------------------------------------------------------------------- /openresty/or_doc/coroutine.md: -------------------------------------------------------------------------------- 1 | # coroutine.create 2 | 3 | *语法:* `co = coroutine.create(f)` 4 | *上下文:* `rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*` 5 | 6 | *使用 Lua 函数创建一个用户态 Lua 协程, 并返回一个协程对象。与标准 Lua 中的协程创建的 API `coroutine.create` 类似,但是工作在 ngx_lua 模块创建的 Lua 协程上下文中,这个 API 第一次是被使用在 0.9.2 版本的 `init_by_lua*` 上下文中。* 7 | 8 | 这个 API 在 v0.6.0 版本第一次释出。 -------------------------------------------------------------------------------- /openresty/or_doc/ngx_ thread.md: -------------------------------------------------------------------------------- 1 | # ngx.config.subsystem 2 | 3 | *语法:* `co = ngx.thread.spawn(func, arg1, arg2, ...)` 4 | *上下文:* `rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*` 5 | 6 | *使用 Lua 函数 `func` 以及可选的参数 `arg1`,`arg2` 等生成一个新的用户“轻线程”,返回一个 Lua 线程(或者 Lua 协程)对象代表这个 “轻线程”* 7 | “轻线程”仅仅是一种特殊的由 `ngx_lua` 模块来调度的 Lua 协程。 8 | 在 `ngx.thread.spawn` 返回之前, `func` 函数将会被使用响应的可选参数进行调用,直到此函数调用返回、或者因为错误而终止或是因为通过使用 Nginx 的 I/O 操作 API 导致请求挂起(如 `tcpsock:receive` 操作)。 9 | 在 `ngx.thread.spawn` 返回后,新被创建的“轻线程”将在各种 I/O 事件中保持通常的异步运行。 10 | 11 | 所有在 `rewrite_by_lua`、`access_by_lua` 和 `content_by_lua` 运行的 Lua 代码块都在一个由 ngx_lua 自动创建的样板“轻线程”中,这些样板“轻线程”通常又叫“入口线程”。 12 | 13 | 默认情况下,相应的 Nginx 处理程序(例如 `rewrite_by_lua` 处理程序)不会终止直到“入口线程”和所有的用户“轻线程”都终止,一个“轻线程(要么是“入口线程”要么是“用户轻线程”因为调用 `ngx.exit`,`ngx.exec`,`ngx.redirect` 或者 `ngx.req.set_uri(uri, true)`)或者“入口线程”因为报错而终止。 14 | 当一个用户“轻线程”因为报错而终止,他将不会像“入口线程”一样终止其他线程的运行。 15 | 16 | 因为 Nginx 子请求模块的限制,一般不允许中止一个正在运行中的 Nginx 子请求。所以同样禁止中止一个运行中的正在等待一个或多个 Nginx 子请求的“轻线程”。你应该调用 `ngx.thread.wait` 来在结束前等待这些“轻线程”结束。这里有个值得注意的例外是你可以通过使用而且只能使用 `ngx.ERROR(-1),408,444或者499` 状态调用 `ngx.exit` 来中止等待的子请求。 17 | 18 | “轻线程”不是使用预先抢占的方式来调度的,换句话说,没有自动执行的时间片,一个“轻线程”将保持在 CPU 运行,直到一个(非阻塞)I/O 操作在一个单线程运行不能被完成。 19 | 20 | The "light threads" are not scheduled in a pre-emptive way. In other words, no time-slicing is performed automatically. A "light thread" will keep running exclusively on the CPU until 21 | 22 | 23 | 24 | 25 | a (nonblocking) I/O operation cannot be completed in a single run, 26 | it calls coroutine.yield to actively give up execution, or 27 | it is aborted by a Lua error or an invocation of ngx.exit, ngx.exec, ngx.redirect, or ngx.req.set_uri(uri, true). 28 | For the first two cases, the "light thread" will usually be resumed later by the ngx_lua scheduler unless a "stop-the-world" event happens. 29 | 30 | User "light threads" can create "light threads" themselves. And normal user coroutines created by coroutine.create can also create "light threads". The coroutine (be it a normal Lua coroutine or a "light thread") that directly spawns the "light thread" is called the "parent coroutine" for the "light thread" newly spawned. 31 | 32 | The "parent coroutine" can call ngx.thread.wait to wait on the termination of its child "light thread". 33 | 34 | You can call coroutine.status() and coroutine.yield() on the "light thread" coroutines. 35 | 36 | The status of the "light thread" coroutine can be "zombie" if 37 | 38 | the current "light thread" already terminates (either successfully or with an error), 39 | its parent coroutine is still alive, and 40 | its parent coroutine is not waiting on it with ngx.thread.wait. 41 | The following example demonstrates the use of coroutine.yield() in the "light thread" coroutines to do manual time-slicing: 42 | -------------------------------------------------------------------------------- /openresty/or_doc/ngx_config.md: -------------------------------------------------------------------------------- 1 | # ngx.config.subsystem 2 | 3 | *语法:* `subsystem = ngx.config.subsystem` 4 | *上下文:* `set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*` 5 | 6 | *这个字符串字段表示了当前基于哪个 Nginx 子系统,对当前模块(ngx_stream_lua_module),这个字段始终返回 “http”,而对 ngx_stream_lua_module 模块,这个字段将返回 “stream”* 7 | 8 | 这个字段在 v0.10.1 版本第一次释出。 9 | 10 | 11 | # ngx.config.debug 12 | 13 | *语法:* `debug = ngx.config.debug` 14 | *上下文:* `set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*` 15 | 16 | *这个布尔字段表示了当前 Nginx 是否打开 debug 编译选项,如编译时配置为 `./configure option --with-debug`。 17 | 18 | 这个字段在 v0.8.7 版本第一次释出。 -------------------------------------------------------------------------------- /openresty/or_doc/ngx_timer.md: -------------------------------------------------------------------------------- 1 | # ngx.timer.at 2 | 3 | *语法:* `ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)` 4 | *上下文:* `init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*` 5 | 6 | *使用一个自定义函数以及可选的自定义参数创建一个 Nginx 计时器* 7 | 8 | 第一个参数 `delay` 以秒为单位指定计时器的延迟时间,支持分秒设置,比如 0.001 在这里表示 1 毫秒延迟。`delay` 同样可以设置为 0 ,此时如果当前句柄正被唤醒则计时器将立即获得执行。(in which case the timer will immediately expire when the current handler yields execution.//TODO yields) 9 | 10 | 第二个参数 `callback` 可以是任何 Lua 函数,后期延迟时间到了,该函数将被以一个后台 “轻线程” 的形式被调用。这个自定义的回调函数将被 Nginx 核心使用 `premature` 参数、user_arg1、user_arg2 等参数自动调用,参数 `premature` 是一个 boolean 值,表示当前定时器是否过期以后,而 user_arg1、user_arg2 等参数就是调用 `ngx.timer.at` 时所传递的余下参数列表。 11 | 12 | 当 Nginx 工作进程尝试关闭,比如在 Nginx 由于收到 HUP 信号而触发了 Nginx 配置重载的时候,或者 Nginx 服务正在关闭的时候,将会出现无效的计时器(//TODO Premature timer)。当 Nginx 工作进程尝试关闭,将无法通过调用 `ngx.timer.at` 来创建一个新的非零延迟的计时器,并且此时 `ngx.timer.at` 将返回 `nil` 和 “process exiting” 错误。 13 | 14 | 这个 API 从 v0.9.3 版本开始,即使 Nginx 工作进程开始关闭的时候,仍然允许创建零延迟计时器。 15 | 16 | 当一个计时器到期时,计时器中用户定义回调的 Lua 代码将在一个与创建这个计时器的源请求完全隔离的 “轻线程” 中运行,所以,源请求生命周期内的对象,比如 `cosockets` 并不能与回调函数共享。 17 | 18 | 下面来看一个简单的例子: 19 | 20 | ```lua 21 | location / { 22 | ... 23 | log_by_lua_block { 24 | local function push_data(premature, uri, args, status) 25 | -- push the data uri, args, and status to the remote 26 | -- via ngx.socket.tcp or ngx.socket.udp 27 | -- (one may want to buffer the data in Lua a bit to 28 | -- save I/O operations) 29 | end 30 | local ok, err = ngx.timer.at(0, push_data, 31 | ngx.var.uri, ngx.var.args, ngx.header.status) 32 | if not ok then 33 | ngx.log(ngx.ERR, "failed to create timer: ", err) 34 | return 35 | end 36 | } 37 | } 38 | ``` 39 | 40 | 还可以创建一个无限执行的计时器,例如,一个每 5 秒触发执行一次的计时器,在它的回调方法中递归的调用 `ngx.timer.at` ,这里给出这样的一个例子。 41 | 42 | ```lua 43 | local delay = 5 44 | local handler 45 | handler = function (premature) 46 | -- do some routine job in Lua just like a cron job 47 | if premature then 48 | return 49 | end 50 | local ok, err = ngx.timer.at(delay, handler) 51 | if not ok then 52 | ngx.log(ngx.ERR, "failed to create the timer: ", err) 53 | return 54 | end 55 | end 56 | 57 | local ok, err = ngx.timer.at(delay, handler) 58 | if not ok then 59 | ngx.log(ngx.ERR, "failed to create the timer: ", err) 60 | return 61 | end 62 | ``` 63 | 64 | 因为定时器的回调函数都是运行在后端,而且他们的运行时间不会叠加到客户端请求的相应时间中,它们可能会因为 Lua 语法错误,或者过多的客户端请求而很容易在服务端造成累积,或者耗尽系统资源。为了防止出现像 Nginx 服务器宕机这种极端结果,在一个 Nginx 工作进程中提供了对 “等待中的计时器” 和 “运行中的计时器” 这两种计时器的数量限制。这里 “等待中的计时器” 是指还没有过期的计时器,而 “运行中的计时器” 是指那些用户回调方法当前正在运行的计时器。 65 | 66 | 一个 Nginx 进程中所允许的 “等待中的计时器” 允许的最大数量由 `lua_max_pending_timers` 指令控制。而允许的 “运行中的计时器” 允许的最大数量由 `lua_max_running_timers` 指令控制。 67 | 68 | 目前的实现,每个 “运行中的计时器” 都会从 nginx.conf 配置中 `worker_connections` 指令配置的全局连接列表中占用一个 (虚) 连接记录,所以必须确保 `worker_connections` 指令设置了一个足够大的值能同时包含真正的连接数和计时器回调函数运行所需要的虚连接数(这个连接数是有 `lua_max_running_timers` 指令设限的)。 69 | 70 | 许多 Nginx 的 Lua API 能在计时器回调函数的上下文中使用,比如操作流和数据包的 cosockets API(`ngx.socket.tcp` 和 `ngx.socket.udp`),共享内存字典(`ngx.shared.DICT`),用户协程函数(`coroutine.*`),用户“轻线程”(`ngx.thread.*`),`ngx.exit`,`ngx.now/ngx.time`,`ngx.md5/ngx.sha1_bin`等都是可用的,但是相关子请求的 API (诸如`ngx.location.capture`),`ngx.req.* API`,下游输出 API (诸如 `ngx.say`,`ngx.print` 和 `ngx.flush`)都是明确在此上下文中不支持的。 71 | 72 | 你可以给计时器的回调函数传递大部分的标准 Lua 值类型(nils、布尔、数字、字符串、表、闭包、文件句柄等),要么显示的使用用户参数或者隐式的使用回调函数闭包的上游值。然而有一些例外诸如:你不能传递任何由 `coroutine.create` 和 `ngx.thread.spawn` 返回的线程对象,或者任何由 `ngx.socket.tcp`、`ngx.socket.udp` 和 `ngx.req.socket` 返回的 cosocket 对象,因为这些对象的生命周期是与创建他们的请求上下文绑定的,而计时器的回调函数(设计时)是与创建他们的请求上下文分离的,并且运行在它自己的(虚)请求上下文中。如果你试图跨越创建这些线程和 cosocket 的请求上下文边界来共享这些线程和 cosocket 对象,将会报错,对线程将报错 `no co ctx found`,对 cosocket 将报错 `bad request`,然而在计时器回调函数内部来创建这些对象则是没问题的。 73 | 74 | 这个 API 在 v0.8.0 版本第一次释出。 75 | 76 | 77 | # ngx.timer.running_count 78 | *语法:* `count = ngx.timer.running_count()` 79 | *上下文:* `init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*` 80 | 81 | *返回当前正在运行的计时器数量。* 82 | 这个指令在 v0.9.20 版本第一次释出。 83 | 84 | 85 | # ngx.timer.pending_count 86 | *语法:* `count = ngx.timer.pending_count()` 87 | *上下文:* `init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*` 88 | 89 | *返回当前正在等待的计时器数量。* 90 | 这个指令在 v0.9.20 版本第一次释出。 -------------------------------------------------------------------------------- /plugins.md: -------------------------------------------------------------------------------- 1 | ##插件 2 | *香草/Vanilla的插件在Vanilla处理请求的过程中提供了六个执行相关逻辑的时机.* 3 | 4 | - *routerStartup 路由开始* 5 | - *routerShutdown 路由结束,已经算出controller和action结果* 6 | - *dispatchLoopStartup 开始准备进入请求转发循环* 7 | - *preDispatch 准备转发(目前的版本0.1.0-rc4,此时机同dispatchLoopStartup重合,后期有可能变化)* 8 | - *postDispatch 请求计算结果获取到后准备POST结果* 9 | - *dispatchLoopShutdown 响应结束,请求完成* 10 | 11 | ###使用 12 | #####*例子:一个管理后台的插件Admin,功能就是对用户权限做一个判定(判断比如这个用户是否已经登录,如果未登录则不允许访问)* 13 | 我们可以在请求路由结束后,已经计算出当前请求需要执行的controller和action的情况下,在AdminPlugin:routerShutdown这个hook添加一个验证的逻辑,如果为登录则跳转到登录页面。 14 | ``` lua 15 | function AdminPlugin:routerShutdown(request, response) 16 | if auth() ~= true then 17 | return ngx.redirect("/login", ngx.HTTP_MOVED_TEMPORARILY) 18 | end 19 | end 20 | ``` 21 | -------------------------------------------------------------------------------- /quick_learning/add_controller.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 controller 2 | *vanilla 的 controller 是业务处理的关键,vanilla 通过对 URI 的路由,找到本次请求对应的 controller 和 action。* 3 | 4 | ###*最简单的 Controller* 5 | *自动生成的 demo 中默认生成了 IndexController 和 index action(`function IndexController:index()`),默认使用简单路由协议(`vanilla.v.routes.simple`)对 URI 进行路由* 6 | 7 | ```lua 8 | local IndexController = {} 9 | 10 | -- curl http://localhost:9110 11 | function IndexController:index() 12 | local view = self:getView() 13 | local p = {} 14 | p['vanilla'] = 'Welcome To Vanilla...' .. user_service:get() 15 | p['zhoujing'] = 'Power by Openresty' 16 | -- view:assign(p) 17 | do return view:render('index/index.html', p) end 18 | return view:display() 19 | end 20 | 21 | -- curl http://localhost:9110/index/action_b 22 | function IndexController:action_b() 23 | return 'index->action_b' 24 | end 25 | 26 | return IndexController 27 | ``` 28 | 29 | #####*以上代码解释* 30 | *关于上面的 controller 实例代码,我们只需关注下面几点* 31 | 32 | * IndexController:index (index Controller 中的 index Action),通过 `self:getView()` 方法获取视图实例 33 | * 可以通过先调用 `view:assign(p)` 将所需要的参数传入视图,再调用 `view:display()` 进行模板渲染,或者可以直接调用 `view:render('index/index.html', p)` 方法,指定需要渲染的模板,并同时传入相应的参数 34 | * 模板参数都是与 LUA 数组的形式进行传递 35 | * 每个 action 的返回值都必须是字符串,所以可以知道 `view:display()` 和 `view:render()` 方法都是返回字符串 36 | * IndexController:action_b (index Controller 中的 action_b Action,这里注意,action 的方法名必须小写),使用默认的简单路由协议,访问 URI 为 `curl http://localhost:9110/index/action_b` 37 | 38 | *注:目前 vanilla 所默认使用的模板引擎是 appo 老师开发的 [resty-template](https://github.com/bungle/lua-resty-template),模板详细的使用文档请移步 appo 老师处参阅。* 39 | 40 | ###*新添加一个 Controller* 41 | *给 Vanilla 添加一个新的 Controller 非常简单,只需要在项目的 controllers 目录,实现一个 LUA 包,包导入的函数即为各个 action, 文件名与 controller 同名。例如添加一个名为 idevz 的 controller, 且实现一个名为 dohello 的 action()。* 42 | 43 | ```lua 44 | local IdevzController = {} 45 | -- curl http://localhost:9110/idevz/dohello 46 | function IdevzController:dohello() 47 | return 'do-hello-action.' 48 | end 49 | return IdevzController 50 | ``` 51 | -------------------------------------------------------------------------------- /quick_learning/debug.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 调试 2 | *除了查看 nginx 错误日志辅助开发外,为了方便 Vanilla 项目的开发和调试,Vanilla 提供了诸如 `print_r` 之类的对象输出方法,以及详细友好的页面报错输出,你不需要到服务器日志去查看,就能所见即所得的开发调试代码.* 3 | 4 | ###sprint_r,print_r,lprint_r,err_log 5 | 6 | #####*sprint_r* 7 | *将 LUA 对象等格式化为易读的字符串返回* 8 | 9 | #####*print_r* 10 | *类似 `ngx.say` 的效果,将对象、变量等以易读的格式进行输出,适用于 Vanilla 开发的 Web 服务* 11 | 12 | #####*lprint_r* 13 | *`print_r` 的 CLI 版本,适用于 v-console 命令行环境* 14 | 15 | ```bash 16 | ╰─○ v-console-0.1.0.rc6 17 | Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio 18 | v-console>a={} 19 | v-console>a.v1='a_v1' 20 | v-console>a.v2='a_v2' 21 | v-console>lprint_r(a) 22 | { 23 | v2 = "a_v2", 24 | v1 = "a_v1" 25 | } 26 | v-console> 27 | ``` 28 | 29 | #####*err_log* 30 | *err_log 方法是对 `ngx.ERR` 的封装,将 `msg` 记录到 nginx 错误日志* -------------------------------------------------------------------------------- /quick_learning/hello_world.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的安装 2 | 3 | ### 安装准备 4 | 5 | 1. 安装好 OpenResty 6 | 2. Vanilla Github 地址:https://github.com/idevz/vanilla 7 | 8 | 9 | ### 安装 10 | 11 | ```bash 12 | # 1.git clone 最新 Vanilla 版本(或者下载相应的 Vanilla release 版本) 13 | git clone https://github.com/idevz/vanilla.git 14 | 15 | # 2. 切换到 Vanilla 文件夹 16 | cd vanilla 17 | 18 | # 3.编译 vanilla: ./setup-framework -v $VANILLA_PROJ_ROOT -o $OPENRESTY_ROOT 其中 $VANILLA_PROJ_ROOT 为 vanilla 框架安装目录。 -o 为 openresty 安装目录 19 | 20 | ./setup-framework -v /application/vanilla -o /application/openresty 21 | 22 | ``` 23 | 24 | *经过这 3 步如果没有报错,则安装 vanilla 成功* 25 | 26 | 27 | ### 创建 vanilla 项目 28 | 29 | ```bash 30 | #1. 创建 vanilla 的运行用户 31 | 32 | useradd -s /sbin/nologin -M nginx 33 | 34 | id nginx # 可以查看到创建的用户 35 | 36 | # 2、创建 vanilla 项目, -a 为 项目路径,-u 为执行用户 -g 为用户组 (在根目录 /home/webserver 下创建名为 cms 的项目) 37 | 38 | ./setup-vanilla-demoapp -a /home/webserver/cms -u nginx -g nginx 39 | 40 | # 3、删掉默认 Nginx 服务 41 | 42 | pkill -9 nginx 43 | 44 | # 4、切换到项目文件夹 编辑项目配置文件,改成你要的 45 | 46 | cd /home/webserver/cms 47 | cd nginx_conf 48 | vim va-nginx.conf 49 | vim va-nginx-development.conf 50 | 51 | # 5、同步配置文件到运行目录 52 | 53 | ./va-cms-service initconf dev -f #开发模式 54 | ./va-cms-service initconf -f #生产模式 55 | 56 | 57 | # 6、启动项目(2选1) 58 | 59 | ./va-cms-service start dev # 启动开发模式 60 | ./va-cms-service start # 启动生产模式 61 | ``` 62 | 63 | *服务启动后,开发环境默认启动在 9110 端口,http://localhost:9110 即可访问* 64 | 65 | ### vanilla 常用命令 66 | 67 | 1. 启动项目: `./va-cms-service start` 或者 `./va-orcms-service start dev` 68 | 69 | 2. 重启项目 `./va-cms-service restart` 或者 `./va-orcms-service restart dev` 70 | 71 | 3. 停止项目: `./va-cms-service stop` 或者 `./va-orcms-service stop dev` 72 | 73 | 4. 创建配置文件 `./va-cms-service initconf dev -f` -------------------------------------------------------------------------------- /quick_learning/models_dao.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 DAO 2 | *vanilla 的 DAO 预设为项目对数据源的封装,一切对数据源的操作都可以封装成 DAO,方便维护、管理、缓存等。 Vanilla 的 DAO 在项目的 models/dao 路径下,一般使用 `LoadModel` 方法进行加载* 3 | 4 | ###*最简单的 DAO* 5 | *由自动生成的 demo 中默认生成了 TableDao,可以看出 TableDao 只是一个普通的 LUA 包。* 6 | 7 | ```lua 8 | local TableDao = {} 9 | 10 | function TableDao:set(key, value) 11 | self.__cache[key] = value 12 | return true 13 | end 14 | 15 | function TableDao:new() 16 | local instance = { 17 | set = self.set, 18 | __cache = {} 19 | } 20 | setmetatable(instance, TableDao) 21 | return instance 22 | end 23 | 24 | function TableDao:__index(key) 25 | local out = rawget(rawget(self, '__cache'), key) 26 | if out then return out else return false end 27 | end 28 | return TableDao 29 | ``` 30 | 31 | #####*以上代码解释* 32 | *DAO 可以是任何对数据层访问封装的 LUA 包,实现方式非常自由。* -------------------------------------------------------------------------------- /quick_learning/models_service.md: -------------------------------------------------------------------------------- 1 | ##Vanilla 的 Service 2 | *vanilla 的 Service 预设为项目对某些通用业务逻辑封装为独立的 Service,方便维护、管理、缓存等。 Vanilla 的 Service 在项目的 models/service 路径下,一般使用 `LoadModel` 方法进行加载* 3 | 4 | ###*最简单的 Service* 5 | *由自动生成的 demo 中默认生成了 UserService,可以看出 UserService 也只是一个普通的 LUA 包。不过 Service 一般调用更底层的 DAO ,并对之做必要封装,并将相关的 Service 暴露给 Controller 使用* 6 | 7 | ```lua 8 | local table_dao = LoadApplication('models.dao.table'):new() 9 | local UserService = {} 10 | 11 | function UserService:get() 12 | table_dao:set('zhou', 'UserService res') 13 | return table_dao.zhou 14 | end 15 | 16 | return UserService 17 | ``` 18 | 19 | #####*以上代码解释* 20 | *Service 可以是任何对数据层访问封装的 LUA 包* -------------------------------------------------------------------------------- /route.md: -------------------------------------------------------------------------------- 1 | ## 路由 2 | *路由是香草/Vanilla的请求分发的关键,这个过程由路由器```vanilla.v.router```和一序列路由协议协同完成(从```vanilla-0.1.0.rc4```开始,vanilla支持两种比较实用的路由协议```vanilla.v.routes.restful```和```vanilla.v.routes.simple```)* 3 | 4 | 5 | - *简单路由协议```vanilla.v.routes.simple```用法* 6 | - *Restful路由协议```vanilla.v.routes.restful```用法* 7 | - *路由实现* 8 | 9 | ### *简单路由协议```vanilla.v.routes.simple```用法* 10 | 11 | 简单路由协议```vanilla.v.routes.simple``` 是Vanilla协议栈中默认使用的协议,不需要特殊配置,直接可用 12 | 13 | ##### *使用Tips:* 14 | 15 | - *URI为根'/'时,```controller```和```action```都默认为```index```* 16 | - *按照URI的路径进行分割,最后的一段为```action```,前面则为```controller```(例如URI为'/a/b/c',则路由结果```controller```为```a.b```,```action```为```c```)* 17 | 18 | ### *Restful路由协议```vanilla.v.routes.restful```用法* 19 | 20 | Restful路由协议```vanilla.v.routes.restful```以一种```map```的形式来配置Vanilla路由规则,提供了更灵活的URL控制,如果需要启用此路由,需要以下几步: 21 | 22 | - *Bootstrap中初始化router* 23 | - *在项目config/路径下放置```restful.lua```文件,并在```restful.lua```中配置相关路由规则* 24 | 25 | ##### *Bootstrap中初始化initRoute,并打开boot_list中的```Bootstrap.initRoute```* 26 | 27 | ```lua 28 | function Bootstrap:initRoute() 29 | local router = self.dispatcher:getRouter() 30 | local restful_route = require('vanilla.v.routes.restful'):new(self.dispatcher:getRequest()) 31 | router:addRoute(restful_route) --此时协议栈中加上默认的vanilla.v.routes.simple,一共两个路由协议,如果只想使用一个路由协议,可以给addRoute传入第二个参数true 32 | end 33 | 34 | function Bootstrap:boot_list() 35 | return { 36 | -- Bootstrap.initWaf, 37 | -- Bootstrap.initErrorHandle, 38 | Bootstrap.initRoute, 39 | -- Bootstrap.initView, 40 | -- Bootstrap.initPlugin, 41 | } 42 | end 43 | ``` 44 | 45 | ##### *项目config/restful.lua配置* 46 | ``` 47 | local restful = { 48 | v1={}, --接口版本定义 49 | v={} --web版本定义 50 | } 51 | 52 | restful.v.GET = { 53 | {pattern = '/user/:user_id', controller = 'test.index', action = 'web_rule'}, 54 | {pattern = '/', controller = 'test.index', action = 'web_root'}, 55 | } 56 | restful.v1.GET = { 57 | {pattern = '/user/:user_id', controller = 'test.index', action = 'api_v1_rule'}, 58 | {pattern = '/', controller = 'test.index', action = 'api_root'}, 59 | {pattern = '/test/index/index', controller = 'test.index', action = 'index'}, 60 | } 61 | 62 | return restful 63 | ``` 64 | 65 | 请求实例(app_name:idevz.org):```curl -X GET -H 'accept: application/vnd.idevz.org.v1.2.3.json' http://localhost:9210/test/index/INDEX``` 66 | 67 | ##### *restful.lua配置Tips:* 68 | 69 | 1. 定义各种版本的空表,如上例子中```v1```和```v```两个版本,```v```后面不跟数字,则表示web服务的版本。 70 | 2. 接口版本的访问需要在请求头(accept)中提供相应的版本信息如:```-H 'accept: application/vnd.idevz.org.v1.2.3.json'``` 71 | 3. 目前支持的方法```GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE,TRACE,CONNECT``` 72 | 73 | ### 路由实现 74 | 75 | *Vanilla通过路由器管理着一个路由协议栈,并通过遍历协议栈上每一个路由协议的```match```方法来获取当前请求的```controller```和```action```* 76 | 77 | 下面是```vanilla.v.router```目前所提供的函数列表: 78 | 79 | ``` 80 | function Router:new(request) --传入request实例初始化路由器,默认已经启用:vanilla.v.routes.simple 81 | function Router:addRoute(route, only_one) --添加路由协议 82 | function Router:removeRoute(route_name) --传入路由协议名称删除路由协议 83 | function Router:getRoutes() --获取当前的路由协议栈 84 | function Router:getCurrentRoute() --获取当前请求所使用的路由协议实例 85 | function Router:getCurrentRouteName() --获取当前请求所使用的路由协议名称 86 | function Router:route() --路由当前请求 87 | ``` 88 | 89 | ##### *路由协议栈* 90 | ```lua 91 | function Router:new(request) 92 | local instance = { 93 | routes = {require('vanilla.v.routes.simple'):new(request)}, 94 | request = request 95 | } 96 | 97 | setmetatable(instance, {__index = self}) 98 | return instance 99 | end 100 | ``` 101 | Router.routes就是Router管理的路由协议栈,默认已经添加```vanilla.v.routes.simple```实例,路由器由一个```request```实例和一个协议栈构成。 102 | 而每个路由协议的关键在于```match```方法,这是返回当前请求走向哪个```controller```和哪个```action```的关键。 103 | ``` 104 | local function route_match(route) 105 | return route:match() 106 | end 107 | 108 | function Router:route() 109 | if #self.routes >= 1 then 110 | local alive_route_num = 0 111 | local route_err = {} 112 | for k,route in ipairs(self.routes) do 113 | if route then 114 | alive_route_num = alive_route_num + 1 115 | local ok, controller_name_or_error, action = pcall(route_match, route) 116 | if ok and controller_name_or_error then 117 | self.current_route = route 118 | return controller_name_or_error, action 119 | else 120 | route_err[k] = controller_name_or_error 121 | end 122 | end 123 | end 124 | error({ code = 201, msg = { 125 | Routes_No_Match = alive_route_num .. "Routes All Didn't Match. Errs Like: " .. tconcat( route_err, ", ")}}) 126 | end 127 | error({ code = 201, msg = {Empty_Routes = 'Null routes added.'}}) 128 | end 129 | ``` 130 | 131 | ##### *路由协议的加载与管理* 132 | 133 | 一张图展示路由器对路由协议栈的管理: 134 | ![Vanilla路由实现原理](route.png) -------------------------------------------------------------------------------- /route.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/route.png -------------------------------------------------------------------------------- /sundry/3rd_party_pkg.md: -------------------------------------------------------------------------------- 1 | ##Vanilla集成的一些优秀第三方包 2 | *这里记录下vanilla中默认集成的一些优秀第三方包.* 3 | - *Waf* 4 | - *模板引擎* 5 | - *工具包* 6 | 7 | ###Waf 8 | #####*[ngx_lua_waf](https://github.com/loveshell/ngx_lua_waf)* 9 | ###模板引擎 10 | #####*[lua-resty-template](https://github.com/bungle/lua-resty-template)* 11 | #####*[openresty-lemplate](https://github.com/openresty/lemplate)* 12 | vanilla-rc7 后默认使用此种模板引擎 13 | ###工具包 14 | #####*[Penlight](https://github.com/stevedonovan/Penlight)* 15 | -------------------------------------------------------------------------------- /sundry/gdb.md: -------------------------------------------------------------------------------- 1 | ## 使用 GDB 调试 Nginx 2 | udo gdb -q -tui # -q 安静模式启动 GDB -tui 显示代码界面 3 | 进入 GDB 运行 `attach` Nginx 子进程报错如下: 4 | issing separate debuginfos, use: debuginfo-install libgcc-4.8.5-4.el7.x86_64 zlib-1.2.7-17.el7.x86_64 5 | 直接安装即可 6 | 7 | ## 断点 8 | ngx_process_events_and_timers 9 | 子进程即 worker 进程在运行后会停留在`epoll_wait` 处等待相应的事件发生,而这个函数调用被封装在 `ngx_process_events_and_timers` 中 10 | 11 | ```gdb 12 | 1 breakpoint keep y 0x000000000046c8f0 in ngx_process_events_and_timers at src/event/ngx_event.c:195 13 | breakpoint already hit 39 times 14 | 2 breakpoint keep y 0x000000000046c93e in ngx_process_events_and_timers at src/event/ngx_event.c:242 15 | breakpoint already hit 36 times 16 | 3 breakpoint keep y 0x000000000046c95a in ngx_process_events_and_timers at src/event/ngx_event.c:249 17 | breakpoint already hit 35 times 18 | 4 breakpoint keep y 0x000000000046ce7d in ngx_event_process_posted at src/event/ngx_event_posted.c:33 19 | 5 breakpoint keep y 0x0000000000475c24 in ngx_epoll_process_events at src/event/modules/ngx_epoll_module.c:793 20 | breakpoint already hit 25 times 21 | 6 breakpoint keep y 0x0000000000475d28 in ngx_epoll_process_events at src/event/modules/ngx_epoll_module.c:926 22 | 7 breakpoint keep y 0x0000000000476022 in ngx_epoll_process_events at src/event/modules/ngx_epoll_module.c:900 23 | breakpoint already hit 28 times 24 | 8 breakpoint keep y 0x000000000048cd4a in ngx_http_wait_request_handler at src/http/ngx_http_request.c:497 25 | breakpoint already hit 6 times 26 | 9 breakpoint keep y 0x000000000048cd6a in ngx_http_wait_request_handler at src/http/ngx_http_request.c:504 27 | breakpoint already hit 7 times 28 | 10 breakpoint keep y 0x000000000048c900 in ngx_http_process_request_line at src/http/ngx_http_request.c:945 29 | breakpoint already hit 6 times 30 | 11 breakpoint keep y 0x000000000048c912 in ngx_http_process_request_line at src/http/ngx_http_request.c:952 31 | breakpoint already hit 6 times 32 | 12 breakpoint keep y 0x000000000048ca95 in ngx_http_process_request_line at src/http/ngx_http_request.c:1011 33 | 13 breakpoint keep y 0x000000000048cbce in ngx_http_process_request_line at src/http/ngx_http_request.c:1027 34 | breakpoint already hit 6 times 35 | 14 breakpoint keep y 0x000000000048c5ef in ngx_http_process_request_headers at src/http/ngx_http_request.c:1322 36 | breakpoint already hit 7 times 37 | 15 breakpoint keep y 0x000000000048c7ed in ngx_http_process_request_headers at src/http/ngx_http_request.c:1342 38 | breakpoint already hit 2 times 39 | 16 breakpoint keep y 0x000000000048c826 in ngx_http_process_request_headers at src/http/ngx_http_request.c:1348 40 | breakpoint already hit 2 times 41 | 17 breakpoint keep y 0x000000000048c231 in ngx_http_process_request at src/http/ngx_http_request.c:1916 42 | breakpoint already hit 2 times 43 | 18 breakpoint keep y 0x0000000000480757 in ngx_http_handler at src/http/ngx_http_core_module.c:839 44 | breakpoint already hit 2 times 45 | 19 breakpoint keep y 0x0000000000484ced in ngx_http_core_rewrite_phase at src/http/ngx_http_core_module.c:910 46 | 20 breakpoint keep y 0x0000000000485e60 in ngx_http_core_content_phase at src/http/ngx_http_core_module.c:1372 47 | breakpoint already hit 1 time 48 | 21 breakpoint keep y 0x0000000000485eac in ngx_http_core_content_phase at src/http/ngx_http_core_module.c:1386 49 | 22 breakpoint keep y 0x0000000000485e7d in ngx_http_core_content_phase at src/http/ngx_http_core_module.c:1379 50 | breakpoint already hit 1 time 51 | 23 breakpoint keep y 0x0000000000504c19 in ngx_http_lua_content_handler at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:222 52 | ``` 53 | 54 | ## Lua 请求处理 55 | ### 堆栈 56 | 57 | ```gdb 58 | 0 __libc_writev (fd=3, vector=0x7ffe08245dd0, count=14) at ../sysdeps/unix/sysv/linux/writev.c:68 59 | 1 0x00000000004717e9 in ngx_writev (c=c@entry=0x7ff03d02f730, vec=vec@entry=0x7ffe08245db0) at src/os/unix/ngx_writev_chain.c:189 60 | 2 0x0000000000476a7e in ngx_linux_sendfile_chain (c=0x7ff03d02f730, in=0x7ff03d001418, limit=2147479551) at src/os/unix/ngx_linux_sendfile_chain.c:215 61 | 3 0x00000000004a7d15 in ngx_http_write_filter (r=0x7ff03cfffcf0, in=0x7ff03d001b78) at src/http/ngx_http_write_filter_module.c:254 62 | 4 0x00000000004a909d in ngx_http_chunked_body_filter (r=0x7ff03cfffcf0, in=) at src/http/modules/ngx_http_chunked_filter_module.c:224 63 | 5 0x00000000004ac7dc in ngx_http_gzip_body_filter (r=0x7ff03cfffcf0, in=0x7ffe082466d0) at src/http/modules/ngx_http_gzip_filter_module.c:326 64 | 6 0x00000000004afd95 in ngx_http_ssi_body_filter (r=0x7ff03cfffcf0, in=) at src/http/modules/ngx_http_ssi_filter_module.c:411 65 | 7 0x00000000004b2cf0 in ngx_http_charset_body_filter (r=0x7ff03cfffcf0, in=0x7ffe082466d0) at src/http/modules/ngx_http_charset_filter_module.c:647 66 | 8 0x0000000000506c7c in ngx_http_lua_capture_body_filter (r=0x7ff03cfffcf0, in=0x7ffe082466d0) at ../ngx_lua-0.10.6/src/ngx_http_lua_capturefilter.c:133 67 | 9 0x0000000000453395 in ngx_output_chain (ctx=ctx@entry=0x7ff03d001428, in=in@entry=0x7ffe082466d0) at src/core/ngx_output_chain.c:74 68 | 10 0x00000000004b4f95 in ngx_http_copy_filter (r=0x7ff03cfffcf0, in=0x7ffe082466d0) at src/http/ngx_http_copy_filter_module.c:152 69 | 11 0x0000000000485a37 in ngx_http_output_filter (r=r@entry=0x7ff03cfffcf0, in=in@entry=0x7ffe082466d0) at src/http/ngx_http_core_module.c:1979 70 | 12 0x0000000000489e33 in ngx_http_send_special (r=r@entry=0x7ff03cfffcf0, flags=flags@entry=1) at src/http/ngx_http_request.c:3358 71 | 13 0x00000000004ffc38 in ngx_http_lua_send_special (flags=1, r=0x7ff03cfffcf0) at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:569 72 | 14 ngx_http_lua_send_chain_link (r=0x7ff03cfffcf0, ctx=, in=0x0) at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:523 73 | 15 0x0000000000501f5f in ngx_http_lua_run_thread (L=L@entry=0x40030378, r=r@entry=0x7ff03cfffcf0, ctx=ctx@entry=0x7ff03d000dc8, nrets=nrets@entry=0) at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:1476 74 | 16 0x00000000005050f0 in ngx_http_lua_content_by_chunk (L=L@entry=0x40030378, r=r@entry=0x7ff03cfffcf0) at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:120 75 | 17 0x000000000050548d in ngx_http_lua_content_handler_file (r=0x7ff03cfffcf0) at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:284 76 | 18 0x0000000000504c21 in ngx_http_lua_content_handler (r=0x7ff03cfffcf0) at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:222 77 | 19 0x0000000000485e7f in ngx_http_core_content_phase (r=0x7ff03cfffcf0, ph=) at src/http/ngx_http_core_module.c:1379 78 | 20 0x0000000000480675 in ngx_http_core_run_phases (r=r@entry=0x7ff03cfffcf0) at src/http/ngx_http_core_module.c:856 79 | 21 0x000000000048075c in ngx_http_handler (r=r@entry=0x7ff03cfffcf0) at src/http/ngx_http_core_module.c:839 80 | 22 0x000000000048c249 in ngx_http_process_request (r=0x7ff03cfffcf0) at src/http/ngx_http_request.c:1916 81 | 23 0x000000000048cbf6 in ngx_http_process_request_line (rev=0x7ff03d069520) at src/http/ngx_http_request.c:1027 82 | 24 0x0000000000476029 in ngx_epoll_process_events (cycle=0x7ff03cffbce0, timer=, flags=) at src/event/modules/ngx_epoll_module.c:900 83 | 25 0x000000000046c947 in ngx_process_events_and_timers (cycle=cycle@entry=0x7ff03cffbce0) at src/event/ngx_event.c:242 84 | 26 0x0000000000473d35 in ngx_worker_process_cycle (cycle=cycle@entry=0x7ff03cffbce0, data=data@entry=0x0) at src/os/unix/ngx_process_cycle.c:753 85 | 27 0x0000000000472820 in ngx_spawn_process (cycle=cycle@entry=0x7ff03cffbce0, proc=0x473cf0 , data=0x0, name=0x6e22f5 "worker process", respawn=respawn@entry=0) 86 | at src/os/unix/ngx_process.c:198 87 | 28 0x0000000000475216 in ngx_reap_children (cycle=0x7ff03cffbce0) at src/os/unix/ngx_process_cycle.c:621 88 | 29 ngx_master_process_cycle (cycle=cycle@entry=0x7ff03cffbce0) at src/os/unix/ngx_process_cycle.c:174 89 | 30 0x000000000044e139 in main (argc=, argv=) at src/core/nginx.c:367 90 | ``` 91 | 92 | ### 断点 93 | 94 | ```gdb 95 | 1 breakpoint keep y 0x000000000048c420 in ngx_http_process_request_headers at src/http/ngx_http_request.c:1185 96 | breakpoint already hit 13 times 97 | 2 breakpoint keep y 0x0000000000504ba0 in ngx_http_lua_content_handler at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:154 98 | breakpoint already hit 13 times 99 | 3 breakpoint keep y 0x0000000000504c98 in ngx_http_lua_content_handler at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:189 100 | 4 breakpoint keep y 0x0000000000504c19 in ngx_http_lua_content_handler at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:222 101 | breakpoint already hit 8 times 102 | 5 breakpoint keep y 0x0000000000505482 in ngx_http_lua_content_handler_file at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:284 103 | breakpoint already hit 8 times 104 | 6 breakpoint keep y 0x0000000000505024 in ngx_http_lua_content_by_chunk at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:54 105 | breakpoint already hit 8 times 106 | 7 breakpoint keep y 0x00000000005050e0 in ngx_http_lua_content_by_chunk at ../ngx_lua-0.10.6/src/ngx_http_lua_contentby.c:120 107 | breakpoint already hit 8 times 108 | 8 breakpoint keep y 0x00000000005014d3 in ngx_http_lua_run_thread at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:1005 109 | breakpoint already hit 22 times 110 | 9 breakpoint keep y 0x0000000000501f58 in ngx_http_lua_run_thread at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:1476 111 | breakpoint already hit 8 times 112 | 10 breakpoint keep y 0x00000000004ffc4a in ngx_http_lua_send_chain_link at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:484 113 | 11 breakpoint keep y 0x00000000004ffb63 in ngx_http_lua_send_chain_link at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:557 114 | breakpoint already hit 7 times 115 | 12 breakpoint keep y 0x00000000004ffb86 in ngx_http_lua_send_chain_link at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:523 116 | breakpoint already hit 6 times 117 | 13 breakpoint keep y 0x00000000004ffc2b in ngx_http_lua_send_chain_link at ../ngx_lua-0.10.6/src/ngx_http_lua_util.c:569 118 | breakpoint already hit 6 times 119 | 14 breakpoint keep y 0x0000000000489e1b in ngx_http_send_special at src/http/ngx_http_request.c:3358 120 | breakpoint already hit 6 times 121 | 15 breakpoint keep y 0x0000000000485a2b in ngx_http_output_filter at src/http/ngx_http_core_module.c:1979 122 | breakpoint already hit 30 times 123 | 16 breakpoint keep y 0x0000000000506c70 in ngx_http_lua_capture_body_filter at ../ngx_lua-0.10.6/src/ngx_http_lua_capturefilter.c:133 124 | breakpoint already hit 30 times 125 | 17 breakpoint keep y 0x00000000004b2ce1 in ngx_http_charset_body_filter at src/http/modules/ngx_http_charset_filter_module.c:647 126 | breakpoint already hit 30 times 127 | 18 breakpoint keep y 0x00000000004afd89 in ngx_http_ssi_body_filter at src/http/modules/ngx_http_ssi_filter_module.c:411 128 | breakpoint already hit 25 times 129 | 19 breakpoint keep y 0x00000000004ad41d in ngx_http_postpone_filter at src/http/ngx_http_postpone_filter_module.c:82 130 | breakpoint already hit 25 times 131 | 20 breakpoint keep y 0x00000000004ac7d0 in ngx_http_gzip_body_filter at src/http/modules/ngx_http_gzip_filter_module.c:326 132 | breakpoint already hit 25 times 133 | 21 breakpoint keep y 0x00000000004a908f in ngx_http_chunked_body_filter at src/http/modules/ngx_http_chunked_filter_module.c:224 134 | breakpoint already hit 25 times 135 | 22 breakpoint keep y 0x00000000004a7cff in ngx_http_write_filter at src/http/ngx_http_write_filter_module.c:254 136 | breakpoint already hit 5 times 137 | 23 breakpoint keep y 0x00000000004769e1 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:92 138 | breakpoint already hit 4 times 139 | 24 breakpoint keep y 0x0000000000476957 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:49 140 | breakpoint already hit 4 times 141 | 25 breakpoint keep y 0x00000000004b4f8a in ngx_http_copy_filter at src/http/ngx_http_copy_filter_module.c:152 142 | breakpoint already hit 5 times 143 | 26 breakpoint keep y 0x000000000045338b in ngx_output_chain at src/core/ngx_output_chain.c:74 144 | breakpoint already hit 5 times 145 | 27 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 146 | breakpoint already hit 1 time 147 | 28 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 148 | breakpoint already hit 1 time 149 | 29 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:21 150 | 30 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 151 | breakpoint already hit 1 time 152 | 31 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 153 | breakpoint already hit 1 time 154 | 32 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 155 | breakpoint already hit 1 time 156 | 33 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 157 | breakpoint already hit 1 time 158 | 34 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 159 | breakpoint already hit 1 time 160 | 35 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 161 | breakpoint already hit 1 time 162 | 36 breakpoint keep y 0x0000000000476a71 in ngx_linux_sendfile_chain at src/os/unix/ngx_linux_sendfile_chain.c:215 163 | breakpoint already hit 1 time 164 | ``` 165 | 166 | ## 使用 GDB 调试 OpenResty 167 | 168 | ### 加断点 169 | 170 | 比如 `ngx_http_lua_ffi_worker_pid` 171 | 172 | ```lua 173 | local ffi = require 'ffi' 174 | local C = ffi.C 175 | 176 | 177 | ffi.cdef[[ 178 | int ngx_http_lua_ffi_worker_pid(void); 179 | ]] 180 | 181 | local _M = { _VERSION = '0.10' } 182 | local mt = { __index = _M } 183 | 184 | function _M.new(self) 185 | local _m_name = 'weibo.com' 186 | return setmetatable({ m_name = _m_name }, mt) 187 | end 188 | 189 | function _M.getWorkerPid(self) 190 | return C.ngx_http_lua_ffi_worker_pid() 191 | end 192 | 193 | return _M 194 | ``` 195 | 运行调用这个包的代码,则可以在 GDB 中加断点 `ngx_http_lua_ffi_worker_pid` 即可直接追踪 OpenResty 的大致运行过程。通过 `c` 继续下一步 196 | 197 | #### breakpoints 198 | ``` 199 | ngx_http_process_request_headers 200 | ngx_http_lua_content_handler 201 | ngx_http_lua_content_handler_file 202 | ngx_http_lua_content_by_chunk 203 | ngx_http_lua_run_thread 204 | ngx_http_lua_send_chain_link 205 | ngx_http_send_special 206 | ngx_http_output_filter 207 | ngx_http_lua_capture_body_filter 208 | ngx_http_charset_body_filter 209 | ngx_http_ssi_body_filter 210 | ngx_http_postpone_filter 211 | ngx_http_gzip_body_filter 212 | ngx_http_chunked_body_filter 213 | ngx_http_write_filter 214 | ngx_linux_sendfile_chain 215 | ngx_http_copy_filter 216 | ngx_output_chain 217 | ngx_linux_sendfile_chain 218 | ``` 219 | -------------------------------------------------------------------------------- /sundry/nginx_phrase.md: -------------------------------------------------------------------------------- 1 | ###Openresty是什么? 2 | 重申一下Openresty是什么?截一张Openresty官网,春哥对Openresty的一个官方说明如下图: 3 | ![Openresty官方说明](openresty-cn.png) 4 | 5 | 我的理解Openresty = Nginx + ngx_http_lua_module + lua_resty_*;它是一个原生Nginx合上一个HTTP_LUA模块,在加上一系列Lua_resty模块组成的一个Ngx_Lua高性能服务生态。 6 | 7 | ###Openresty处理HTTP请求的执行阶段 8 | Openrestry处理HTTP请求的执行阶段来自于Nginx,Nginx的HTTP框架依据常见的处理流程将处理阶段划分为11个阶段,其中每个处理阶段可以由任意多个HTTP模块流水式地处理请求,Openresty通过ngx_http_lua_module将Lua特性嵌入Nginx,ngx_http_lua_module属于一个Nginx的HTTP模块,为高性能服务开发封装了7个相应HTTP请求处理阶段如下: 9 | - *set_by_lua* 10 | - *content_by_lua* 11 | - *rewrite_by_lua* 12 | - *access_by_lua* 13 | - *header_filter_by_lua* 14 | - *body_filter_by_lua* 15 | - *log_by_lua* 16 | 17 | 有同学会发现,Openresty所提供的LUA解析指令还有以下两个: 18 | - *init_by_lua* 19 | - *init_worker_by_lua* 20 | ```init_by_lua```作用在配置加载阶段,```init_worker_by_lua```作用在worker进程初始化阶段,并非HTTP请求处理阶段。 21 | 22 | 另外,需要重点提一下的是,Nginx输出过滤器是流式处理模型,一个数据块body filter就被调用一次。可以用以下简单的例子测试验证: 23 | *nginx.conf* 24 | ``` 25 | http { 26 | # use sendfile 27 | sendfile on; 28 | 29 | # Va initialization 30 | lua_package_path "...;;"; 31 | lua_package_cpath "...;"; 32 | lua_code_cache off; 33 | 34 | init_by_lua_block {ngx.log(ngx.ERR, '=======>init')} 35 | init_worker_by_lua_block {ngx.log(ngx.ERR, '=======>init_worker')} 36 | rewrite_by_lua_block {ngx.log(ngx.ERR, '=======>rewrite')} 37 | access_by_lua_block {ngx.log(ngx.ERR, '=======>access')} 38 | header_filter_by_lua_block {ngx.log(ngx.ERR, '=======>header_filter')} 39 | body_filter_by_lua_block {ngx.log(ngx.ERR, '=======>body_filter')} 40 | log_by_lua_block {ngx.log(ngx.ERR, '=======>log')} 41 | 42 | 43 | server { 44 | # List port 45 | listen 7200; 46 | set $template_root ''; 47 | set_by_lua_block $a {ngx.log(ngx.ERR, '=======>set'); return 'xxx'} 48 | 49 | # Access log with buffer, or disable it completetely if unneeded 50 | access_log logs/development-access.log combined buffer=16k; 51 | # access_log off; 52 | 53 | # Error log 54 | error_log logs/development-error.log; 55 | 56 | # Va runtime 57 | location / { 58 | content_by_lua_block { 59 | ngx.log(ngx.ERR, '=======>content') 60 | ngx.say('----------') 61 | ngx.say('---ccc-------') 62 | ngx.say('---vvvv-------') 63 | ngx.say('---vdddv-------') 64 | ngx.say('---ggvv-------') 65 | } 66 | 67 | # content_by_lua_file ./pub/index.lua; 68 | } 69 | } 70 | } 71 | ``` 72 | 73 | *logs/development-error.log截取* 74 | ``` 75 | set_by_lua:1: =======>set 76 | rewrite_by_lua(development-nginx.conf:31):1: =======>rewrite 77 | access_by_lua(development-nginx.conf:32):1: =======>access 78 | content_by_lua(development-nginx.conf:60):2: =======>content 79 | header_filter_by_lua:1: =======>header_filter 80 | body_filter_by_lua:1: =======>body_filter 81 | body_filter_by_lua:1: =======>body_filter 82 | body_filter_by_lua:1: =======>body_filter 83 | body_filter_by_lua:1: =======>body_filter 84 | body_filter_by_lua:1: =======>body_filter 85 | body_filter_by_lua:1: =======>body_filter 86 | log_by_lua(development-nginx.conf:35):1: =======>log while logging request 87 | ``` 88 | 可以看出body_filter的执行次数等于ngx.say数量加一 -------------------------------------------------------------------------------- /sundry/ngx_re.md: -------------------------------------------------------------------------------- 1 | ###Openresty 环境中正则表达式使用示例积累 2 | 3 | *一些觉得比较有代表性的使用方式都收集到这里* 4 | 5 | ####精确匹配字符 6 | 7 | *要求 citycode 的值必须是前4位为字符,后4位为数字的字符串* 8 | 9 | ```lua 10 | local query_str = [[citycode=CHXX0056×tamp=1487127951]] 11 | local args = ngx.decode_args(query_str, 0) --解析 query_string 获取的字段数组 12 | local str = args['citycode'] 13 | local rs1,rs2, err = ngx.re.find(str, [[^([A-Z]{4})([0-9]{4})$]]) --正则查找 14 | print_r(rs1) 15 | print_r(rs2) 16 | ``` -------------------------------------------------------------------------------- /sundry/openresty-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/openresty-cn.png -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/1.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/10.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/100.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/101.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/101.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/102.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/102.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/103.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/103.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/104.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/104.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/105.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/105.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/106.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/106.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/107.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/107.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/108.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/108.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/109.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/109.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/11.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/110.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/110.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/111.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/111.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/112.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/112.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/113.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/113.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/114.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/114.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/115.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/115.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/116.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/116.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/117.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/117.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/118.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/118.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/119.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/119.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/12.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/120.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/120.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/121.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/121.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/122.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/122.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/123.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/123.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/124.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/124.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/125.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/125.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/126.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/126.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/127.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/127.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/128.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/13.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/14.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/15.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/16.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/17.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/18.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/19.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/2.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/20.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/21.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/22.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/23.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/24.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/25.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/26.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/27.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/28.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/29.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/29.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/3.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/30.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/31.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/32.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/33.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/34.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/35.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/35.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/36.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/37.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/38.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/39.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/4.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/40.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/41.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/41.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/42.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/42.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/43.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/43.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/44.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/44.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/45.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/45.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/46.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/46.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/47.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/47.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/48.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/48.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/49.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/49.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/5.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/50.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/51.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/51.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/52.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/52.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/53.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/53.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/54.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/54.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/55.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/55.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/56.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/56.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/57.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/57.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/58.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/58.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/59.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/59.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/6.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/60.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/60.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/61.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/61.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/62.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/62.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/63.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/63.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/64.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/64.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/65.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/65.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/66.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/66.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/67.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/67.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/68.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/68.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/69.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/69.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/7.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/70.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/70.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/71.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/71.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/72.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/72.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/73.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/73.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/74.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/74.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/75.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/75.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/76.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/76.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/77.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/77.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/78.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/78.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/79.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/79.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/8.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/80.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/80.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/81.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/81.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/82.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/82.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/83.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/83.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/84.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/84.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/85.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/85.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/86.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/86.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/87.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/87.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/88.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/88.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/89.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/89.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/9.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/90.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/90.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/91.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/91.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/92.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/92.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/93.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/93.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/94.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/94.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/95.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/95.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/96.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/96.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/97.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/97.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/98.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/98.jpg -------------------------------------------------------------------------------- /sundry/qcon2015brokenperformancetools/99.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/sundry/qcon2015brokenperformancetools/99.jpg -------------------------------------------------------------------------------- /sundry/qcon_2015_broken_performance_tools.md: -------------------------------------------------------------------------------- 1 | ###QCon 2015 Broken Performance Tools 2 | *分享一个Brendan Gregg大神[QCon 2015分享](http://www.slideshare.net/brendangregg/qcon-2015-broken-performance-tools)* 3 | 4 | ![1.jpg](qcon2015brokenperformancetools/1.jpg) 5 | 6 | ![2.jpg](qcon2015brokenperformancetools/2.jpg) 7 | 8 | ![3.jpg](qcon2015brokenperformancetools/3.jpg) 9 | 10 | ![4.jpg](qcon2015brokenperformancetools/4.jpg) 11 | 12 | ![5.jpg](qcon2015brokenperformancetools/5.jpg) 13 | 14 | ![6.jpg](qcon2015brokenperformancetools/6.jpg) 15 | 16 | ![7.jpg](qcon2015brokenperformancetools/7.jpg) 17 | 18 | ![8.jpg](qcon2015brokenperformancetools/8.jpg) 19 | 20 | ![9.jpg](qcon2015brokenperformancetools/9.jpg) 21 | 22 | ![10.jpg](qcon2015brokenperformancetools/10.jpg) 23 | 24 | ![11.jpg](qcon2015brokenperformancetools/11.jpg) 25 | 26 | ![12.jpg](qcon2015brokenperformancetools/12.jpg) 27 | 28 | ![13.jpg](qcon2015brokenperformancetools/13.jpg) 29 | 30 | ![14.jpg](qcon2015brokenperformancetools/14.jpg) 31 | 32 | ![15.jpg](qcon2015brokenperformancetools/15.jpg) 33 | 34 | ![16.jpg](qcon2015brokenperformancetools/16.jpg) 35 | 36 | ![17.jpg](qcon2015brokenperformancetools/17.jpg) 37 | 38 | ![18.jpg](qcon2015brokenperformancetools/18.jpg) 39 | 40 | ![19.jpg](qcon2015brokenperformancetools/19.jpg) 41 | 42 | ![20.jpg](qcon2015brokenperformancetools/20.jpg) 43 | 44 | ![21.jpg](qcon2015brokenperformancetools/21.jpg) 45 | 46 | ![22.jpg](qcon2015brokenperformancetools/22.jpg) 47 | 48 | ![23.jpg](qcon2015brokenperformancetools/23.jpg) 49 | 50 | ![24.jpg](qcon2015brokenperformancetools/24.jpg) 51 | 52 | ![25.jpg](qcon2015brokenperformancetools/25.jpg) 53 | 54 | ![26.jpg](qcon2015brokenperformancetools/26.jpg) 55 | 56 | ![27.jpg](qcon2015brokenperformancetools/27.jpg) 57 | 58 | ![28.jpg](qcon2015brokenperformancetools/28.jpg) 59 | 60 | ![29.jpg](qcon2015brokenperformancetools/29.jpg) 61 | 62 | ![30.jpg](qcon2015brokenperformancetools/30.jpg) 63 | 64 | ![31.jpg](qcon2015brokenperformancetools/31.jpg) 65 | 66 | ![32.jpg](qcon2015brokenperformancetools/32.jpg) 67 | 68 | ![33.jpg](qcon2015brokenperformancetools/33.jpg) 69 | 70 | ![34.jpg](qcon2015brokenperformancetools/34.jpg) 71 | 72 | ![35.jpg](qcon2015brokenperformancetools/35.jpg) 73 | 74 | ![36.jpg](qcon2015brokenperformancetools/36.jpg) 75 | 76 | ![37.jpg](qcon2015brokenperformancetools/37.jpg) 77 | 78 | ![38.jpg](qcon2015brokenperformancetools/38.jpg) 79 | 80 | ![39.jpg](qcon2015brokenperformancetools/39.jpg) 81 | 82 | ![40.jpg](qcon2015brokenperformancetools/40.jpg) 83 | 84 | ![41.jpg](qcon2015brokenperformancetools/41.jpg) 85 | 86 | ![42.jpg](qcon2015brokenperformancetools/42.jpg) 87 | 88 | ![43.jpg](qcon2015brokenperformancetools/43.jpg) 89 | 90 | ![44.jpg](qcon2015brokenperformancetools/44.jpg) 91 | 92 | ![45.jpg](qcon2015brokenperformancetools/45.jpg) 93 | 94 | ![46.jpg](qcon2015brokenperformancetools/46.jpg) 95 | 96 | ![47.jpg](qcon2015brokenperformancetools/47.jpg) 97 | 98 | ![48.jpg](qcon2015brokenperformancetools/48.jpg) 99 | 100 | ![49.jpg](qcon2015brokenperformancetools/49.jpg) 101 | 102 | ![50.jpg](qcon2015brokenperformancetools/50.jpg) 103 | 104 | ![51.jpg](qcon2015brokenperformancetools/51.jpg) 105 | 106 | ![52.jpg](qcon2015brokenperformancetools/52.jpg) 107 | 108 | ![53.jpg](qcon2015brokenperformancetools/53.jpg) 109 | 110 | ![54.jpg](qcon2015brokenperformancetools/54.jpg) 111 | 112 | ![55.jpg](qcon2015brokenperformancetools/55.jpg) 113 | 114 | ![56.jpg](qcon2015brokenperformancetools/56.jpg) 115 | 116 | ![57.jpg](qcon2015brokenperformancetools/57.jpg) 117 | 118 | ![58.jpg](qcon2015brokenperformancetools/58.jpg) 119 | 120 | ![59.jpg](qcon2015brokenperformancetools/59.jpg) 121 | 122 | ![60.jpg](qcon2015brokenperformancetools/60.jpg) 123 | 124 | ![61.jpg](qcon2015brokenperformancetools/61.jpg) 125 | 126 | ![62.jpg](qcon2015brokenperformancetools/62.jpg) 127 | 128 | ![63.jpg](qcon2015brokenperformancetools/63.jpg) 129 | 130 | ![64.jpg](qcon2015brokenperformancetools/64.jpg) 131 | 132 | ![65.jpg](qcon2015brokenperformancetools/65.jpg) 133 | 134 | ![66.jpg](qcon2015brokenperformancetools/66.jpg) 135 | 136 | ![67.jpg](qcon2015brokenperformancetools/67.jpg) 137 | 138 | ![68.jpg](qcon2015brokenperformancetools/68.jpg) 139 | 140 | ![69.jpg](qcon2015brokenperformancetools/69.jpg) 141 | 142 | ![70.jpg](qcon2015brokenperformancetools/70.jpg) 143 | 144 | ![71.jpg](qcon2015brokenperformancetools/71.jpg) 145 | 146 | ![72.jpg](qcon2015brokenperformancetools/72.jpg) 147 | 148 | ![73.jpg](qcon2015brokenperformancetools/73.jpg) 149 | 150 | ![74.jpg](qcon2015brokenperformancetools/74.jpg) 151 | 152 | ![75.jpg](qcon2015brokenperformancetools/75.jpg) 153 | 154 | ![76.jpg](qcon2015brokenperformancetools/76.jpg) 155 | 156 | ![77.jpg](qcon2015brokenperformancetools/77.jpg) 157 | 158 | ![78.jpg](qcon2015brokenperformancetools/78.jpg) 159 | 160 | ![79.jpg](qcon2015brokenperformancetools/79.jpg) 161 | 162 | ![80.jpg](qcon2015brokenperformancetools/80.jpg) 163 | 164 | ![81.jpg](qcon2015brokenperformancetools/81.jpg) 165 | 166 | ![82.jpg](qcon2015brokenperformancetools/82.jpg) 167 | 168 | ![83.jpg](qcon2015brokenperformancetools/83.jpg) 169 | 170 | ![84.jpg](qcon2015brokenperformancetools/84.jpg) 171 | 172 | ![85.jpg](qcon2015brokenperformancetools/85.jpg) 173 | 174 | ![86.jpg](qcon2015brokenperformancetools/86.jpg) 175 | 176 | ![87.jpg](qcon2015brokenperformancetools/87.jpg) 177 | 178 | ![88.jpg](qcon2015brokenperformancetools/88.jpg) 179 | 180 | ![89.jpg](qcon2015brokenperformancetools/89.jpg) 181 | 182 | ![90.jpg](qcon2015brokenperformancetools/90.jpg) 183 | 184 | ![91.jpg](qcon2015brokenperformancetools/91.jpg) 185 | 186 | ![92.jpg](qcon2015brokenperformancetools/92.jpg) 187 | 188 | ![93.jpg](qcon2015brokenperformancetools/93.jpg) 189 | 190 | ![94.jpg](qcon2015brokenperformancetools/94.jpg) 191 | 192 | ![95.jpg](qcon2015brokenperformancetools/95.jpg) 193 | 194 | ![96.jpg](qcon2015brokenperformancetools/96.jpg) 195 | 196 | ![97.jpg](qcon2015brokenperformancetools/97.jpg) 197 | 198 | ![98.jpg](qcon2015brokenperformancetools/98.jpg) 199 | 200 | ![99.jpg](qcon2015brokenperformancetools/99.jpg) 201 | 202 | ![100.jpg](qcon2015brokenperformancetools/100.jpg) 203 | 204 | ![101.jpg](qcon2015brokenperformancetools/101.jpg) 205 | 206 | ![102.jpg](qcon2015brokenperformancetools/102.jpg) 207 | 208 | ![103.jpg](qcon2015brokenperformancetools/103.jpg) 209 | 210 | ![104.jpg](qcon2015brokenperformancetools/104.jpg) 211 | 212 | ![105.jpg](qcon2015brokenperformancetools/105.jpg) 213 | 214 | ![106.jpg](qcon2015brokenperformancetools/106.jpg) 215 | 216 | ![107.jpg](qcon2015brokenperformancetools/107.jpg) 217 | 218 | ![108.jpg](qcon2015brokenperformancetools/108.jpg) 219 | 220 | ![109.jpg](qcon2015brokenperformancetools/109.jpg) 221 | 222 | ![110.jpg](qcon2015brokenperformancetools/110.jpg) 223 | 224 | ![111.jpg](qcon2015brokenperformancetools/111.jpg) 225 | 226 | ![112.jpg](qcon2015brokenperformancetools/112.jpg) 227 | 228 | ![113.jpg](qcon2015brokenperformancetools/113.jpg) 229 | 230 | ![114.jpg](qcon2015brokenperformancetools/114.jpg) 231 | 232 | ![115.jpg](qcon2015brokenperformancetools/115.jpg) 233 | 234 | ![116.jpg](qcon2015brokenperformancetools/116.jpg) 235 | 236 | ![117.jpg](qcon2015brokenperformancetools/117.jpg) 237 | 238 | ![118.jpg](qcon2015brokenperformancetools/118.jpg) 239 | 240 | ![119.jpg](qcon2015brokenperformancetools/119.jpg) 241 | 242 | ![120.jpg](qcon2015brokenperformancetools/120.jpg) 243 | 244 | ![121.jpg](qcon2015brokenperformancetools/121.jpg) 245 | 246 | ![122.jpg](qcon2015brokenperformancetools/122.jpg) 247 | 248 | ![123.jpg](qcon2015brokenperformancetools/123.jpg) 249 | 250 | ![124.jpg](qcon2015brokenperformancetools/124.jpg) 251 | 252 | ![125.jpg](qcon2015brokenperformancetools/125.jpg) 253 | 254 | ![126.jpg](qcon2015brokenperformancetools/126.jpg) 255 | 256 | ![127.jpg](qcon2015brokenperformancetools/127.jpg) 257 | 258 | ![128.jpg](qcon2015brokenperformancetools/128.jpg) 259 | 260 | 261 | ### 社区组织 262 | #### *QQ群&&微信公众号* 263 | - *Openresty/Vanilla 开发 1 群:205773855* 264 | - *Openresty/Vanilla 开发 2 群:419191655* 265 | - *Openresty 技术交流 1 群:34782325* 266 | - *Openresty 技术交流 2 群:481213820* 267 | - *Openresty 技术交流 3 群:124613000* 268 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 269 | 270 | ![vanilla](va_c.jpeg) 271 | 272 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /update.md: -------------------------------------------------------------------------------- 1 | ##升级 2 | 3 | *vanilla-0.1.0.rc5是vanilla-0.1.0.rc4在新浪移动全线推广过程中针对一些工程化部署问题改进版本,可以肯定的一点vanilla-0.1.0.rc4在功能、扩展性、使用方面表现良好,非常适合移动业务的场景,更不止于API,但是在集群部署、多App部署、Vanilla框架升级等方面vanilla-0.1.0.rc4存在短板,而vanilla-0.1.0.rc5极大程度的弥补了这些短板。* 4 | 5 | ### *推荐始终使用最新版的Vanilla* 6 | *当前Vanilla最新版本0.1.0.rc7,支持命令:* 7 | 8 | - vanilla-0.1.0.rc7(*你没看错,自0.1.0.rc5起,vanilla的命令行和框架代码都带着版本号,方便多版本共存,也方便框架升级*) 9 | - v-console-0.1.0.rc7 10 | 11 | 12 | ### 社区组织 13 | #### *QQ群&&微信公众号* 14 | - *Openresty/Vanilla 开发 1 群:205773855* 15 | - *Openresty/Vanilla 开发 2 群:419191655* 16 | - *Openresty 技术交流 1 群:34782325* 17 | - *Openresty 技术交流 2 群:481213820* 18 | - *Openresty 技术交流 3 群:124613000* 19 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 20 | 21 | ![vanilla](va_c.jpeg) 22 | 23 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) -------------------------------------------------------------------------------- /va_c.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla-zh/b12453531da944c0ad61b04373cc7226ef91f71c/va_c.jpeg -------------------------------------------------------------------------------- /vanilla_user_practice/README.md: -------------------------------------------------------------------------------- 1 | ###Vanilla使用经验 2 | *这部分是Vanilla的使用者在使用过程中的一些体验、发现、想法、感受等等* 3 | 4 | 以下为格式 5 | ###Nginx相关 6 | #####*nginx phrase* 7 | ###框架本身 8 | #####*我理想中的Web框架* -------------------------------------------------------------------------------- /vanilla_user_practice/shi_yong_jing_yan.md: -------------------------------------------------------------------------------- 1 | # Vanilla使用经验 2 | 3 | -------------------------------------------------------------------------------- /vanilla_user_practice/yong_hu_lie_biao.md: -------------------------------------------------------------------------------- 1 | # 用户列表 2 | 3 | --------------------------------------------------------------------------------