学习OpenResty

2014-08-21

  从入职HDF开始,就发现程序的世界慢慢的变大了。那个时候读了很多技术方面的书籍,也总想着研究甚至参与开源项目。其中,最想研究当属nginx和lua了,我对于C/C++并不熟悉,也没有实际的项目可以参与,便想着阅读代码来加强理解和学习,而且,还能够同时研究网络、程序语言,学习模块化设计,难得啊。那个时候,脑袋中只是有这样的一个概念,也没有准确的目的,便找来了nginx的源代码,从入口函数起始,慢慢的往里面的模块深入。
  最除接触到OpenResty项目时,觉得没有什么大的用途。如果需要应用服务器,Tomcat和PHP应该能做的更好。今年换了项目,老大要求游戏登录服务器、好友服务器、gateway都采用OpenResty+Lua 来实现。起初,我对这种做法也感到有点奇怪。后来调研多了,才发现原来这样的做法是多么简便。如果自己写带网络功能的程序来实现,可想而知会有一大波坑会在前面等着你。
  nginx的module机制非常好,能够很好的集成各种第三方module。大神 agentzh 的lua-nginx-module 把lua 作为一个nginx module,再把整体打包成为OpenResty。我一直想要彻底搞明白了的脚本语言绑定,通过学习这个module终于算完成了。其实也非常简单,Lua本身是纯C写的,继承到C/C++程序中,最主要的工作,其实就是把Lua的内部数据结构暴露出来让C++代码访问,把C/C++ 数据结构封装成Lua数据结构让Lua代码访问。把数据封装好了,就可以让Lua和C++互相调用函数了。很简单的就能想到,Lua调用C/C++函数,肯定是以函数指针的方式进行的。lua_register(L, "c_function_name", function_pointer); 这个lua内核函数就能够把C函数导出为Lua运行时的一个symbol:function_name,function_name就变成了一个Lua函数名字。当想要在C/C++中调用Lua函数,就需要使用 lua_getglobal(L,"luaFunc"); ) 获取Lua函数symbol,其实是获取它的函数指针放在栈上,再使用lua_pushinteger() 放入参数,使用lua_pcall() 调用该函数,最后使用lua_gettop() 获取返回值。交互的本质就是获取函数指针。
  nginx的directive机制,把nginx.conf变成了一个极为简单的语言,增强了配置文件的表述能力。真的很佩服设计出这种模式的作者。这也给了我一些启发,虽然配置文件一般不需要被设计为一个DSL,但是,尽量接近DSL还是可以的。
  Lua 的coroutine也是非常有用的特性。当我们需要在OpenResty中同时访问redis、mysql、其他server时,我们不希望一处的网络等待造成时间片浪费。这里就可以使用coroutine来实现并发。但是,coroutine不会像线程那样主动等待另外一个线程,所以,我们需要手动遍历coroutine集合来等待它们都完成。
  这段时间,看了nginx和lua-nginx-module的源代码,发现强制类型转换在C语言中其实挺常见的。自己没有写过大规模的C程序,不知道当程序规模增大后这种类型cast对于代码的稳定性影响如何。另外一方面,优秀的代码中,macro的使用的确少了,且规范。
  我一直想要简单的改改Lua语法,来加强自己对于编译原理的理解。一直都没有时间来做。希望这一两年能够做好这个任务。对于网络部分,或者说IO部分,我依然没有什么兴趣。它不是我想要解决的问题核心部分。

  P.S.  我只是在看,就不知道需求是什么,无法从需求出发,无法理解openresty整个结构。因为我主要的兴趣点在图形渲染,对于这个项目的学习并没有投下全部精力。学习到当下的这种程度,对于我当前已经足够了。

 

 

《深入理解nginx:模块开发与架构解析》
《Nginx HTTP Server》 

如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)