|
精华帖 (9) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2008-02-24 关键字: erlang python cgi fastcgi
ErLang Web
ErLang语言从一开始,就是针对并发设计的。ErLang作为一个平台,在稳定性和实时性方面也有不俗的表现。不少人希望把ErLang应用在Web领域。 ErLang Inets里面包括HTTP Server、FTP Server等。ErLang的Web开发框架叫做YAWS(Yet Another Web Server)。如果说Inets相当于Apache HTTP Server的地位,那么YAWS就相当于Servlet Server的地位。 一些优秀的程序员为ErLang开发了ORM持久层、Template层等。但是,由于ErLang的几项缺点,使得ErLang在Web开发领域举步维艰。这些缺点包括: (1)字符串处理能力弱。I/O(输入输出)能力也不强。 对于大量处理HTML的Web应用程序来说,这是一个致命缺陷。 (2)变量值只能赋值一次。不能修改。 这意味着,除了I/O(输入输出)之外,ErLang应用程序是无状态的,无副作用的。也意味着,我们难以在ErLang程序中用基本数据结构存放可以改变的状态。对于普通程序员来说,这种限制会带来编程的难度。这并不是不可逾越的障碍,只是需要思路上的转换。 (3)ErLang不支持循环,只能用递归表示循环。 对于普通程序员来说,这也是一个不小的挑战。程序员需要习惯Map、Reduce等函数,简化需要循环的编程。程序员还需要习惯于把大量的数据作为参数在各个层次之间函数调用传来传去,因为ErLang不支持成员变量。这一点有点类似于浏览器和服务器之间把状态信息传来传去,以保证服务器的无状态性(Stateless)。 (2)(3)两个问题并不是不可逾越的鸿沟,只是一种编程模型上的转换。但是第一个问题是无法回避的问题。 人们想到了一种方法,把字符串处理工作交给其他语言(比如Python、Ruby、Perl等)来做。这种思路需要考虑的问题是,ErLang如何同其他语言进行交互通信? 如果ErLang中存在Python、Ruby等语言的解释器,那就好了。这个思路有些强人所难了。ErLang最不擅长的就是处理字符串,更别说解释一门语言了。 如果Python、Ruby等语言可以直接编译为ErLang虚拟机指令,那也是个不错的选择。目前还没有这方面的项目出现。从实现难度上考虑,Python、Ruby里面的语法元素映射不容易为ErLang虚拟机指令,比如,类、对象、循环、变量多次赋值、环状数据结构等。 ErLang本身提供了Jinterface和erl_interface两种语言接口。Jinterface用来和Java程序通信,erl_interface用来和C语言程序通信。 Java可以通过JNI(Java Native Interface)调用C语言程序。C语言程序和Java程序运行在同一个进程中。 Jinterface和erl_interface的例子表明,ErLang和其他语言的交互模式和JNI不同。ErLang和其他语言程序各自运行在不同的ErLang Node当中。两个Node只能进行通信,而不能进行函数调用,顶多只能通过通信渠道进行远程函数调用(RPC)。 既然都是远程通信,Jinterface和erl_interface也没有什么特殊的。Python、Ruby等语言一样可以和ErLang进行通信。常见的通信手段比如Socket。 在一个ErLang Web应用程序中,ErLang和Python之间的通信过程可能如下: ErLang Web应用程序收到HTTP Request,根据URL把处理过程转到一个handle函数中。 handle(Request … ) -> Model = getModel(…), %% 根据参数获取数据 View = getView(… ), %%这里的View通常是一个Template文件名 HTML = send( [Context, View] ) %% 经过通信渠道,发到Python语言程序中 %% HTML是一个Binary。ErLang输出HTML到浏览器 . Python语言从通信渠道收到数据流,解析出来Context和View,然后根据View读取一个Template文件,并且把Context和Template结合起来,产生HTML,发还给ErLang程序。 我们看到,这里面涉及到一次大数据量通信——Python把HTML发送到ErLang。这种时间空间效率是否能够忍受呢?我们能否做出改进呢? ErLang和Python之间的这种通信过程,和CGI/FastCGI的工作方式很类似。都是跨进程传输HTML。我们来看CGI/FastCGI的模型。 CGI输出重定向 CGI的全称是Common Gateway Interface。CGI程序一般安装在一个支持CGI的HTTP Server中,比如Apache HTTP Server。 CGI程序和HTTP Server之间的流程和上述的ErLang/Python通信过程类似: HTTP Server收到HTTP Request之后,根据URL把处理转到对应的CGI程序中。 CGI程序通过环境变量或者参数等渠道,获取HTTP Request等信息,查询数据库获取数据,然后产生HTML,输出到标准输出(STDOUT)。实际上是利用输入输出重定向(I/O Redirect)把HTML传回给HTTP Server。 如果操作系统不支持输入输出重定向,那么HTTP Server自己就需要分配一个缓冲区,存放CGI程序输出的HTML,然后,HTTP Server把缓冲区里面的HTML输出到浏览器。这个过程和上述的ErLang/Python通信情况差不多。 如果操作系统支持标准输入输出重定向,而且可以重新定向到Socket,那么CGI程序也许可以把HTML直接通过Socket写入浏览器端,而不需要把HTML发回到HTTP。不过,CGI程序一般都是把HTML重定向输出回服务器。 字符串处理进程直接把结果写入浏览器Socket ErLang/Python通信和CGI/FastCGI模式的输出模式比较相似。 浏览器和Web Server建立Socket连接,Web Server把字符串处理工作交给另外一个进程的字符串处理程序,字符串处理程序把字符串处理结果传回到Web Server,最后由Web Server把HTML通过Socket传回给浏览器。 那么,字符串处理程序能否直接把HTML通过Socket发到浏览器呢? 这好像很难。虽然Socket句柄只是一个整数,但是进程间似乎不能共享Socket(和文件句柄)同级别的资源。 我们知道,ErLang程序最终是通过Socket把HTML传给浏览器的。Sokect句柄是一个整数,我们能否把Socket句柄直接传给Python程序,然后让Python程序直接把HTML写到Socket里面,就相当于直接传输到浏览器里面。 在同一个进程中,多个线程可以共享进程的资源,包括Socket句柄,文件句柄等等。两个进程之间,就不能共享Socket句柄了。 上述是我的思考。涉及到很多我不了解的领域。请大家指正。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2008-02-24
如果Erlang只是扮演你描述的这个角色,完全没有使用它的必要啊,这部分用C写不是更高效?
|
|
| 返回顶楼 | |
|
最后更新时间:2008-02-24
ErLang的并发效率比较高,正适合做Web Server。
我本来的想法是,只把ErLang 做 Web URL -> Action 的 Dispatcher部分。 相当于支持CGI 的 HTTP Server。 考虑到 ErLang有一个不错的内存数据库 mnesia,因此还在 ErLang 部分里面保留了 Model 部分。 C语言做 Web Server/URL Dispatcher 比 ErLang 的效率要高吗? |
|
| 返回顶楼 | |
|
最后更新时间:2008-02-24
C总是可以写出更高效的代码。。Erlang的效率还没办法和C相比。
并发逻辑比较复杂的时候,C可能需要很多代码,你这里Erlang经过裁减以后的功能并不复杂,用C并不难实现。比如nginx的并发能力也很强,用它跑CGI应该会超过Erlang+Python。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-02-25
|
|
| 返回顶楼 | |
|
最后更新时间:2008-02-25
ngix的实现架构,比起 lighttpd, apache httpd 等,有什么优势呢?
网上搜索了一下,这方面的资料很少。 Bit String 好象只能用于 Binary 操作 -- 用List Comprehension 的方式操作 Binary Bit。 Web Server 最终输出到浏览器的是 Bytes, 是 Binary. HTML可以分为静态和动态两个部分。假设浏览器编码为 unicode。 所有的静态文本部分在服务端都可以保持为 Bytes 即 Binary 的状态。不必变化。 动态部分在输出的时候,转换成 unicode 编码的 binary. 假设这么一段动态HTML文本。 <HTML> <Body> Hello, ${name} </Body> </HTML> 这段文本可以分为 三个部分。输出过程为 首先输出静态 bytes <HTML> <Body> Hello, 其次输出动态变量 ${name} 的值。 这个${name} 的值需要转化为unicode编码的 Binary (Bytes) 假如这个${name}的值来自于数据库,如果数据库里面的值直接就是unicode的bytes类型。那么,连编码转换工作都省略了。 最后输出静态 bytes </Body> </HTML> 从这种思路来看,ErLang Template 完全可以不涉及到任何 String List 操作。 假设我们已经有了一个这样的节点为 Binary 的 ErLang Template Tree,我们就可以高效地实现 ErLang Template Tree + Data Model = HTML。 因此,HTML输出效率问题,并不是阻碍 ErLang Web的关键因素。 主要问题在于 Template 的解析工作。ErLang 很不擅长字符串解析工作。 ErLang XML 解析器的效率和功能排在很多语言后面。 HTML Template的解析工作,可以交给其他的语言,比如,Python,Ruby来做。 只需要解析一次。解析之后的 Template Tree 导入到 ErLang 语句,以后就可以重复使用了。 除了Template解析之外,其他的工作,还是在ErLang中完成。 这里又有一个问题,如何把Template解析结果导入到ErLang中。 如果用 Tuple, List之类的类型映射,用通信通道进行传输,还需要多定义一套协议。这把问题更加复杂化了。 这很像 Servlet -> JSP -> TagLib 的过程。不仅没有解决问题,反而人为地添加了不必要的复杂度。 最好的选择是,直接把Template解析结果导入ErLang的Mnesia数据库。这样,ErLang就可以直接使用 Template Tree了。而且管理上也会方便许多。 找了半天,也没有发现 Mnesia 针对其他语言的 import data 标准接口。而且发现,mnesia 和 其他数据库的数据交换支持非常薄弱。export data功能好像只提供了一个dump。 找来找去,竟然找不到一个合适的数据交换格式。 想了想,也许可以把整个Template Tree + Data Model = HTML 字符串处理工作,都外包给外部程序,比如python和ruby。当然,这种做法的代价是,同时有 ErLang 和 Python 两个相互通信的 VM 运行。增加了系统架构的复杂性。 如果有合适的数据导入导出格式,我还是比较倾向于前面的思路。 Python 解析 HTML 的 Template ,导入到 ErLang 的某个树形存储结构,以便ErLang语言可以直接使用。这样的结构最简单。只是交换各式的问题不容易解决。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-02-25
既然template是final的,就让它慢慢解析好了.一个template解析一分钟都无所谓.
|
|
| 返回顶楼 | |
|
最后更新时间:2008-02-25
ErLang写解析器的难度太高了。
一个用来解决问题的技术,如果实现难度较高,那么不仅不会解决问题,还会增加更多的问题。 我想,大部分的问题,都应该有简单的解法,或者简单的解法组合。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-02-26
buaawhl 写道 ErLang写解析器的难度太高了。 一个用来解决问题的技术,如果实现难度较高,那么不仅不会解决问题,还会增加更多的问题。 我想,大部分的问题,都应该有简单的解法,或者简单的解法组合。 FP写解析器要比命令语言简单很多.... 无论是图灵完备的还是不完备的语义,都能用递归式简单的表达。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-02-28
buaawhl 写道 ErLang写解析器的难度太高了。 一个用来解决问题的技术,如果实现难度较高,那么不仅不会解决问题,还会增加更多的问题。 我想,大部分的问题,都应该有简单的解法,或者简单的解法组合。 Erlang写解析器合适的很,简单一点的用pattern match处理;复杂一点的有yecc,我处理过好几种自己定义的模版,都是这么完成的。 另外,Erlang处理字串(List)的能力不弱啊,甚至encode的转换,自己写也很顺。 |
|
| 返回顶楼 | |








