欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ErLang / Python Web 的类似CGI/FastCGI模式 博客分类: Web ErlangPythonCGIWeb设计模式 

程序员文章站 2024-03-18 22:25:16
...

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句柄了。

上述是我的思考。涉及到很多我不了解的领域。请大家指正。