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

《编程机制探析》第二十二章 互联网应用

程序员文章站 2022-05-17 13:44:24
...
《编程机制探析》第二十二章 互联网应用

在前面的章节中,我们一直在编程的基本原理和模型中折腾。从本章起,我们将进入真正的应用程序的世界。
《黑客帝国》中,莫菲斯递给尼奥一粒药丸,“欢迎来到真实的世界。”
在计算机界中,也有“真实的世界”(Real World)的说法。比如,我们经常看到这样的话:这种方案看起来很美,但不适用于真实的世界。(That sounds great, but not for real world.)
我不喜欢真实的世界,我只喜欢在理想的模型中畅游。历经多年的应用开发,我早已明白,真实的世界是嘈杂的、琐碎的、无聊的。你很难把东西做得很漂亮,很满意。
为了避免误解,我这里澄清一下。我并非完美主义者,也没有精益求精的精神。我只是希望能够达到一种基本的要求:写出来的东西,用户满意,我自己也满意。
做到这点很难吗?貌似不难,实际却相当难。尤其是复杂度到了一定级别的系统,想做到各方都满意,那几乎是不可能的任务(mission impossible)。
在我使用软件的经验中,只有一些功能简单、明确、固定的小软件,才能让我感到基本满意。
只要软件具有了一定的规模,就一定会有很多不如意的地方。我们(这里,我们是甲方,即软件用户的角色)之所以使用那些软件,不是因为我们喜欢它们,而是因为别无选择。我们只能瘸子里拔将军,从众多不如意中,选一个差强人意的。
这里面有个用户需求问题。用户的需求,都是从现实世界中来的。而程序员要实现需求,则必须根据计算机模型来实现,需要把现实世界中的需求映射到计算机模型中。这两个模型之间,经常存在着难以跨越的鸿沟。程序员怪用户不懂计算机,用户怪程序员不懂业务。最终,妥协的总是程序员。因为,脱离于实际应用的软件是没有用处的,也很难卖到钱。所以,程序员必须紧跟用户的需求。
当用户的需求比较固定的时候,程序员的工作就轻松许多。当用户的需求经常变动的时候,程序员可就苦也。
应用软件大致可以分为两类——产品和项目。产品是指针对某一种行业的通用的软件产品,项目是指针对某一个公司具体业务的软件项目。
有些公司是做网站运营的,不卖产品,而是卖服务。这种运营服务,也可以看做是一种产品。
产品的优点很多。
第一,利润高。写一个好产品,可以卖给整个行业内多家客户。
第二,需求稳定,程序员不需要疲于奔命地应对用户层出不穷的新需求。
产品的缺点也是很明显的。
第一,开发周期长,成本高。一个好产品,从底层架构、功能实现到用户界面,都需要良好的设计。
第二,同质化竞争激烈。由于需求固定稳定,大家都可以了解和学习这些通用的需求,都可以做这类产品,因此竞争激烈。
项目的优缺点和产品正好倒过来。
项目周期短,来钱快。但是,项目的特点是劳动力密集型。没项目时,得养一大帮闲人。项目一旦多了,马上就需要大量的人。想要赚更多的钱,就得接更多的项目,跟起来就越累。这就是劳动力密集型产业的弱点。相对的,产品只需要几个或者十几个核心开发人员即可。赚钱多少,不依赖于人数,而依赖于产品质量。
以上的优缺点是针对软件公司老总来说的。对于程序员来说。做项目积累的经验是博而杂,做产品积累的经验是少而精。
喜欢做项目,还是喜欢做产品,这要看个人偏好。在我看来,大部分程序员都是喜欢做产品的。因为做项目很累,学到的东西又很散很浅。
但是,真实的世界正好是倒过来的。软件行业中,大部分的职位都是做项目的,少部分才是做产品的。因为,通用产品的需求是固定的,胜者通吃,一两家好的产品,就足以霸占整个行业市场了。而项目就灵活许多了,大大小小那么多公司,每个公司都有不同的需求,软件公司永远不愁没有项目做,只要你吃苦耐劳,并且愿意把自己的利润降到极点。
产品难,项目累,何方才是出路?出路在于项目和产品之间的桥梁。针对一系列中小型公司的种种特殊需求,开发出一系列灵活多样的产品。项目可以容易地产品化,产品也可以容易地项目化(定制化)。这应该是软件业的共识了。
好了,鸟瞰完软件行业的真实世界,我们回到地面,来看一些真实世界中的具体问题。
在前面的章节中,我们讨论的各种编程模型,都是基于单一进程的模型,很少涉及到跨进程的模型。
但是,在真实的世界中,所有的软件模型都是跨进程的。道理很简单,我们前面已经讲过了。独自运行在内存中、不和外部打交道的程序是没有意义的。一个程序要有用处,则必须要有I/O(输入/输出),既要接受用户的指令,又要把执行结果输出到外围设备(硬盘、屏幕、打印机、网络等),才能为人所知,才能为人所用。
前面讲过,而所有的I/O,都是和进程外部状态交互,都是跨进程的。比如,最简单的文件操作,实际上就是调用了操作系统的文件管理进程和硬盘控制驱动进程。再比如,最简单的屏幕显示操作,实际上就是调用了操作系统中安装的显卡驱动进程。
简单的I/O如此,复杂的I/O就不用说了。我们来看一个典型的互联网(Internet)应用的例子。这是个很常见、也很重要的例子。在这个例子中,我们将学习到关于互联网应用(也叫做web应用)的知识。现代的软件中,互联网软件占了很大份额,提供了大多数的工作岗位。其重要性不容忽视。这也是本章的主题。
我们先从互联网用户的角度来看。
一个用户打开网页浏览器,访问千里之外的某个网站(Web Site),看到了一个页面。这里面发生了什么事情呢?
首先,浏览器是一个进程。浏览器进程要根据网址访问互联网上的一个网站,它应该怎么做呢?它应该像一条鱼一样,顺着网线游出去,到处打听,找到那个网站,然后,叼了内容,再游回来吗?
不是这样的。它先把网址包装一下,发给操作系统的网络服务进程。然后,网络服务进程就负责剩下的工作。当然,网络服务进程也不会像鱼一样游出去。它只是把网络请求再次包装一下,就转交给网卡驱动进程了。然后,网卡驱动进程再次把网络请求包装一下,就把网络请求信息通过网线,或者无线网络,发送到本局域网中的路由器上去了。
这里,原本的网址请求经过浏览器、网络服务进程、网卡驱动进程的一层层包装,已经膨胀为一个包了好几层的大包裹了。
在这个过程中,涉及到极为重要的网络协议层概念。这是计算机网络编程的核心概念。这方面的内容有很多,写得也很透。我没什么可发挥的,这里只是简述一下。
在现实的编程模型中,网络协议层分为应用层、TCP层、IP层、网卡层。
其中,TCP层也叫做传送层(Transport Layer)。TCP就是Transmission Control Protocol(传输控制协议)的缩写。
IP层也叫做互联网络层(Internet Layer)。IP就是Internet Protocol(互联网络协议)的缩写。在互联网上,每一个直接连接到互联网上的计算机、路由器或者其他设备,都有一个唯一的独立的IP地址。
有读者问了,IP层有地址,TCP层没有地址吗?TCP层是没有地址的。TCP层只有端口(Port),叫做TCP端口,是应用进程向本机网络服务进程申请到的一个整数。用来标志某个TCP通信结点。
TCP端口和IP地址通常是合在一起使用的,合称TCP/IP地址。比如,192.168.1.1是一个IP地址。9052是一个TCP端口。那么,192.168.1.1:9052就是一个TCP/IP地址。
需要注意的是,目前的IP地址大都是4段,叫做IP4,已经不敷使用。以后的IP地址正在向6段发展,叫做IP6,那时候的IP地就是133.189.192.168.1.1这样的了。
在实际的网络服务实现中,TCP/IP也通常作为一层,叫做TCP/IP层。TCP协议和IP协议也通常合称为TCP/IP协议,是网络编程中最为重要的协议。
TCP/IP协议是一个有始有终、有来有回、有请求有反馈的协议。在一个典型的TCP/IP场景中,TCP/IP地址都是成对出现的。一个是客户主机(即浏览器所在的计算机)的TCP/IP地址。一个是服务主机(即目标网站所在的主机)的TCP/IP地址。
一般来说,服务主机的TCP/IP地址(即IP地址和TCP端口)都是公开在互联网公共网络上,是固定不变的,是唯一的公网地址。而客户主机的IP地址只是一个局域网内部的IP地址,只在本网内有意义。至于客户主机中,某个应用程序(比如浏览器)的TCP端口,那更是随即分配的,只在整个网络请求的周期内有意义,用完就丢。
IP层之下,就是网卡层了,也叫做物理层。为了明晰起见,我叫它网卡层。至少现在的计算机架构中还需要网卡。
对应到前面的例子中。浏览器就是应用层。它接受的网址格式,需要遵守相应的应用层网络协议。其中最重要的一种应用层网络协议就是HTTP(Hypertext Transfer Protocol,超链接文本传输协议)。这东西,大家也应该耳闻能详了,无需费舌。如有不明之处,请自行到网上查阅。你看看浏览器地址栏中的内容,打头的就应该是HTTP这几个字母。
网络服务进程负责处理TCP/IP协议,对应的是TCP/IP层。这个网络服务进程有可能是一个进程,同时处理TCP/IP协议。也有可能是两个进程,一个处理TCP协议,一个处理IP协议。还有可能是多个进程,分担着多个TCP和IP协议的处理。
浏览器负责把HTTP协议格式的网址,包装成TCP协议的格式,然后,输出到网络服务进程。HTTP协议包装成TCP协议的过程,有些复杂。
大部分情况下,浏览器需要调用互联网上的DNS(Domain Name Service,域名服务),把网址(即域名)转换成IP地址。这也是一个颇为复杂的服务。这里先不多讲。
网络服务进程负责把TCP协议包装成IP协议,转给网卡驱动进程。网卡驱动进程在IP协议包上在加上自己的网卡物理地址(Mac Address),就把网络协议包顺着网线发出去了。
网络中有一个重要的角色,叫做路由器(Router)。路由器是构成所有网络的基石,无论是局域网,还是互联网。
路由器是一个人际高手,维护着一个巨大的社交网络。二十一世纪,什么最重要?人脉!路由器有一个花名册,其中记录了相连的其他路由器的关系网,这个花名册叫做路由表。依靠着这个巨大的关系网,路由器就可以把经由自己的网络协议包正确地转发给下一个路由器。
网络协议包就像一个四处托关系求人办事的人,总是先从最近的关系户(路由器)打听。路由器就像一个热心的中介人一般,再把网络协议包介绍给关系网中下一个离目标主机更近的中介人(路由器)。
需要注意的是,路由器只解析IP层和物理层。路由器只关心目标IP地址。对于路由器来说,TCP端口和HTTP协议内容都属于不可理解的内容,它对此也漠不关心。
局域网中的路由器接到网络协议包,在外面添加上自己的IP地址和网卡物理地址,根据自己的路由表,就把网络协议包发了出去。这时候,网络协议包就出了局域网,进入了外网(即互联网)。
互联网上的道路和现实世界中的道路一样,是分级别的。分国道、省道、市道、县道。互联网的各个级别的道路上,都分布着各个级别的路由器。
一路上,网络协议包遇到了很多路由器。这些路由器都很热心,甚至过于热心。他们都把这个协议包拆开看一看,看到里面的目标IP地址之后,就去查自己的路由表,看看这事儿能不能帮上忙。路由表中记录了一些相邻路由器的信息。如果路由器觉得帮不上忙,就把协议包扔了,让别人去操心。如果能帮上忙,就把协议包继续向路由表中的下一个路由器传。注意,外网路由器在转包的过程中,是不会添加自己的IP地址的,他还没有热心到这种程度。所以,网络协议包的去程和回程,不一定遵守同一条路线。完全是途中的路由器随即决定的。
网络协议包如同接力棒一般,在互联网上的路由器之间传递着。这种传递,通常是从下级路由器到上级,道路宽度从细到宽,比如,可能从电话线ADSL到光纤。然后再从上级到下级,找到目的网站。
终于找到组织了。网络协议包热泪盈眶。目标网站主机抓到这个网络协议包之后,就不再转发,而是自行处理。至于怎么处理的,暂且不谈。我们回顾一下网络协议包在路由器关系网中的四处寻觅的艰辛路程。
网络协议包一旦出了本机(浏览器所在的主机),就进入了路由器的关系网络,直到最终到达目标网站主机。网络协议包出了本机,在路由器关系网络中畅游的整个过程中,一直是在IP协议层和物理层两层中打转。
当网络协议包就脱离了路由器的关系网,进入了目标主机之后,就进入了更高的协议层——TCP层和HTTP层。
目标主机的网络服务进程,接到了网络协议包之后,根据其中的目标TCP端口(这是目标网站进程的TCP端口),把网络协议包转发给到本机内运行的网站进程。至此,一次TCP/IP协议层上的通信,就完成了一半。
网站进程收到了网络协议包之后,取出其中的HTTP协议内容,就开始忙活,最后得到一个结果(通常是一个页面)。然后,网站进程再把结果打包成一个结果协议包,向客户浏览器所在的局域网的路由器的IP地址发送。这个过程和来时一样。路漫漫而修远兮,吾将上下而求索。不再细述。
路由器接收到结果网络包之后,发现目标IP地址正是自己的IP地址,就抓了下来,不再转发。路由器首先将自己添加的IP地址和物理地址剥去,里面就露出了客户主机的局域网IP地址和物理地址。然后,路由器就把网络协议包发向局域网。客户主机受到这个包之后,就知道自己要的东西到了,一个Nice Catch,抓住,就开始处理。这个过程类似于网站的处理过程。客户主机的网络服务进程先根据TCP端口(浏览器的TCP端口)把网络协议包发给浏览器进程。至此,一次TCP/IP通信就完整地结束了。有始有终,有来有去,有请求有反馈。然后,浏览器进程再处理其中的HTTP协议内容,把网页显示到屏幕上。
需要提醒的是,为了简化起见,我们假设一个网络包去,一个网络包回。在真实的世界中,并不一定如此。如果网络协议包过大的话,会被拆成多个小包。细节是魔鬼。诚不我欺。真实的世界中,充满了各种各样的琐碎细节。
我们可以看到,一次简单的网站访问,牵扯到多少人力和物力。可想而知,互联网路上是多么繁忙,各式各样的网络协议包四处流窜。
值得庆幸的是,浏览器进程并不需要知道这些。浏览器进程只知道申请一个TCP端口,把HTTP请求发过去就行了。这就是网络协议分层的意义所在。各层管各层的事情。
对于浏览器来说,一次复杂的互联网访问,和一次本机的文件访问,没有什么太大区别,都是对进程外部状态的I/O(输入/输出)。
以上的流程,是从客户端(浏览器)的角度来看的。对于我们开发人员来说,我们更关注的是服务器(网站主机)一端的实现。这就是本章及后续章节的主题——Web应用。
这里,我们要说明一下internet和web的区别。Internet是互联网的意思,这是一个计算机术语,是一个新词。Web是一个老词,原意是蛛网。Internet更广义一些,internet应用(互联网应用)包括所有基于互联网的软件,包括小软件,也包括大型网站。而Web则狭义一些,web应用主要指网站。本章的题目叫做互联网应用,但这么写只是为了好看,实际上,本章及后续章节的主要内容就是网站开发,即Web应用。
现在,让我们把目光转向服务端,看看在一次典型的网站访问中,网站主机中发生了什么。
基于网络协议分层的机制,我们不需要考虑TCP/IP层以下的事情。我们只需要考虑HTTP协议层。
当网站接收到浏览器(客户端)发来的HTTP协议包的时候,就会进行相应处理,提供结果,反馈给客户端。这个处理过程有可能非常简单,也有可能非常复杂。
在互联网刚刚出现的原始年代,网站提供的内容都是静态的,只需要根据客户请求,找到相应的网页文件,发给客户就是了。什么叫网页文件?就是HTML文件。HTML是Hyperlink Text Markup Language(超链接文本标记语言)的缩写,是一种XML格式的文本。
静态内容就是一系列的HTML文件。每个HTML文件中通常包括HTML文本、CSS(cascade style sheet,用来定义HTML元素的格式)、Javascript、图片等。其中,图片是最大的资源,其余的都是文本资源,个头比较小。
每个HTML文件都有自己的网址,HTML文件中包含的每一个资源,比如,CSS、Javascript、图片等,也都有自己的网址。因此,一次HTTP请求并不是一次就玩了,通常会引起一系列的内含资源的HTTP请求。
在寂静年代,只需要一个网页设计师,就可以建设一个网站。
历史的车轮总是滚滚向前。随着技术的发展,用户的口味越来越重,错了,是越来越丰富多样,静态内容已经无法满足用户的精神需求了。这时候,就出现了动态内容。于是,网站的建设方式发生了深刻的变化。在静态内容时代,网站建设领域是网页设计师的天下。到了动态内容时代,网站建设领域就成了程序员的天下。因为,动态内容的提供,必须要通过程序。
一开始的时候,典型的动态内容网站的架构是这样的。一个Web Server(也叫做HTTP Server)中,配置了一个个CGI(Common Gateway Interface,公共网关接口)程序。
这些程序为什么叫做CGI程序?我是不太了解的。我进入Web开发领域的时候,CGI模式已经是一种过时的开发模式,虽然还在广泛使用,但是已经不为追赶新潮的程序员所喜。
Gateway是网关的意思,表示内网(局域网)到外网(互联网)的关口,通常就是指局域网的出口路由器。CGI应该就是指网站入口点的意思吧。
CGI程序可以是编译语言,但更多的是解释语言,因为解释语言无需编译,更加方便。由于这个原因,CGI程序通常被称为CGI脚本(Script,通常指一小段解释程序的代码)。
CGI的一个主要问题在于效率问题。当用户发来一个动态内容请求的时候,Web Server就得把对应的CGI进程运行起来。处理完请求之后,再结束进程。也就是,每一个请求都对应一个进程的生灭。而进程是相当昂贵的资源。
除此之外,还有一个原因。那就是CGI模式下,CGI脚本都是一个个分离的脚本程序,彼此之间很难共享什么东西。一个用户的每一次请求都相当于一次独立的请求。一个用户的多次请求,很难形成连续的关系。
这在动态内容时代的初期,不是什么问题。但是,随着用户的要求越来越高,用户希望自己的一连串请求之间,能够连续起来,保持一定的状态。这种一连串请求之间的状态保持,有一个专有名词,叫做Session(会话,会谈)。因为客户端和服务器端之间的一连串请求、反馈就像两个人你一句我一句谈话一样。
两个人初次邂逅,还不认识,等搭上了第一句话之后,就开始热情地交谈起来。这时候,两个人就成了熟人,每一句话都可以建立在前一句的话的基础上,而不用每一次都需要重新搭话。这就形成了一种客户端和服务器端之间的连续的会话状态。
会话(Session)的需求同时对HTTP协议和Web开发模式提出了要求。
HTTP一开始是无状态的协议,一次HTTP请求就是一次TCP/IP连接,然后就断开,结束了。但是,随着时代的发展,无状态的HTTP不能满足人们的需求,人们又在HTTP协议上增加了状态。这是非常重要的概念,我们后面有专门的章节来讲解。
用户连续多次请求之间的状态保持,不仅需要HTTP协议的支持,还需要Web开发模式的支持。因为Web Server总得找个地方把用户的一连串请求的状态存放起来,以便该用户的后续请求可以共享这些状态。在CGI模式下,CGI脚本之间是分离的。要想共享状态,只能借用文件、数据库、网络服务器等进程外I/O存储设备,而且每次都得打开/关闭外部的I/O设备,这个开销也是不小。
为了解决CGI模式的问题,Application Server(应用服务器,简称App Server)的开发模式出现了。App Server是一个独立运行的服务进程。它通过TCP协议与web server交互。当web server遇到动态内容请求时,就把请求转发给App Server处理。App Server就会启动一个线程来处理该请求。
App Server的模式好在哪里呢?首先,线程比进程轻量一些。其次,所有的处理请求的线程都运行在同一个进程空间内,因此,可以共享进程内的资源,最主要的是内存资源,还有一些保持打开状态的I/O设备。
App Server模式一出现,立刻大行其道,占据了CGI模式的不少份额。我赶上的就是App Server这一拨。App Server模式给了程序员偌大的发挥*。各种层次不穷的网站开发架构模式就是在App Server的构架上创建出来的,并影响到App Server模式以外的领域,比如,CGI模式。
App Server同时也是HTTP Server,可以单独作为Web Server来运行。一个App Server就可以同时处理静态内容请求和动态内容请求。
不过,术业有专攻,App Server专攻动态内容请求,在处理静态内容请求方面不是很擅长。因此,App Server常和Web Server一起组合使用。App Server负责处理动态内容请求,Web Server负责静态内容请求。因为,动态HTML页面中经常含有各种静态资源(比如,很多图片资源),所以,一次动态内容请求,通常会引起十几次静态资源请求。
一次典型的动态内容请求的过程是这样的。App Server收到HTTP请求,就把HTTP请求转发给内部运行的某个网站应用程序(Web Application,简称web app)。一个App Server里面可以跑多个web app,但通常情况下,只跑一个web app。
Web app收到HTTP请求之后,就回去查找动态内容,典型的,是在一个数据库中查找。Web app需要访问App Server进程之外的数据库进程,并获取查询结果。然后,web app根据查询结果,拼装成一个HTML页面,再交给App Server进行后续的处理。动态拼装页面的技术有个名字,叫做模板(Template)技术。这曾经是很重要的一个技术。那时候,各种模板技术层出不穷,争芳斗艳。
历史的车轮继续向前滚动。随着时间的推移,web应用有了长足的进展。无论是在前台(指发送到浏览器的HTML页面部分)还是后台(指服务器端),都发生了深刻的变化。
首先来看前台HTML部分。动态HTML页面的产生,有两种方式。一种是后台服务器端生成。一种是由HTML页面包含的Javascript生成。
第一种方式就是我们提到的Template(模板)技术。第二种方式中,浏览器中的Javascript可以获取用户的操作,直接向后台服务器发送HTTP请求,然后把动态内容取回来,填充到当前的HTML应用中。这种技术有很多名字,ajax,富客户端(Rich Client),等等。这些表述都不太直观。在本书中,我使用Javascript HTTP这个词。
随着Google公司的在线文档办公软件和Gmail的推出(这两个卓越的产品都是用Javascript开发的),Javascript HTTP技术奠定了自己坚实的基础,逐渐成为了web应用交互的主流开发模式。
与此同时,其他的富客户端(Rich Client)技术也进入了人们的视野,主要是Adobe公司的Flash技术。不过,这不在本书讨论之列,先不去管它。
随着Javascript HTTP技术的兴起,HTML页面越来越静态化,曾经喧嚣一时的Template技术逐渐失去了用武之地,陷入了沉寂,慢慢淡出了人们的视野。当然,Template技术的地位只是降低了,并不是消失了。而且,Template还广泛地用于其他各种需要动态生成文本的领域,比如,动态生成代码和查询语句,等等。
以上是前台的状况。我们现在把目光投向后台。服务器端的发展主要在于架构的扩展上。随着用户越来越多,请求越来越多,网站规模也越来越大,一个服务器已经不能满足要求了。这时候,集群(Cluster)技术就出现了。局域网中的多台服务器组合在一起,共同响应用户的请求,这种架构叫做集群(Cluster)。
一个典型的集群架构是这样的。局域网内的计算机分为三层。第一层是十几台或者更多的Web Server,负责应对用户浏览器对静态页面资源(静态文本和图片)的请求。第二层是几台App Server,负责应对用户浏览器对动态页面资源的请求。第三层是一台或者两台数据库服务器(db server),用来响应App Server的请求。
Web Server上全都是静态文件资源,每台Web Server上的静态资源都是一样的,不会改变,是无状态的,因此可以任意扩展。Web Server可以有任意多台,上百台,上千台都可以,甚至可以放到局域网外的互联网上任何一个网络结点上。这也是静态网站的常见策略。
App Server由于需要保持用户会话(Session)状态的,可扩展性就受到了限制。当App Server集群和某个浏览器之间建立了用户会话(Session)关系,那么,该集群必须保证,下一次用户请求过来的时候,还能够找到这个会话状态。实现方案主要有三种。
第一种方案,叫做Session Sticky(粘住会话)。意思就是,当一个浏览器访问集群中某一台App Server时,建立了会话关系。下一次该浏览器请求再次过来的时候,还由这台App Server负责接待。这就像客户专员原则一样。一个客户服务人员跟踪服务一个客户,一直到底。而不是每次都换一个客服人员。
这种方案的缺点在于,难以实现负载平衡。有的App Server客人多,有的App Server客人少,无法最大限度地发挥集群的效能。
第二种方案,叫做Session Replication(会话复制)。意思就是,当一个浏览器访问集群中某一台App Server时,建立了会话关系。那么,该会话关系会广播(Broad)到集群中的其它App Server中。下一次该浏览器请求再次过来的时候,任何一台App Server都可以负责接待。
这种方案的优点在于容易实现负载平衡,大家的工作量都差不多。缺点在于制造了大量的网络通信。
第三种方案,叫做Session Cache Center(会话缓存中心)。意思就是,专门用一个服务器来存储用户的所有会话状态。当一个浏览器访问集群中某一台App Server时,建立了会话关系。这个App Server自己不保存这种关系,而是交给客户关系经理,即会话缓存中心。下一次该浏览器请求再次过来的时候,任何一台App Server都可以负责接待。这台App Server首先要去会话缓存中心服务器中查找是否已经存在了该会话关系,如果已经存在,那么就取出来继续用,如果不存在,就建立一个会话关系。处理完毕之后,再把更新后的会话状态存回到会话缓存中心服务器中。
这种方案的优点在于结构简单,实现容易,也不会产生网络广播,而且,缓存中心不仅可以用来缓存会话状态,还可以缓存其他信息。这种方案的缺点在于,一旦缓存中心出了问题,所有App Server都得忙乱一番,失去响应一段时间。不过,这种缺点可以用备份缓存中心来缓解。因此,这种方案被大量采用。
由于会话缓存中心这种方案的兴起,CGI开发模式又焕发了新的生机。在这种Session方案下,App Server模式和CGI模式站在了同一个起点上。大家处理Session都是要进行网络通信。谁也别说谁。而且,在CGI模式下,还可以省掉App Server。可以直接把CGI脚本放置在Web Server中,这节省了成本和资源。
而且,现在还有一种说法。多进程模式比单进程模式更加健壮。在单进程模式下,一个线程出了问题,可能会引起整个进程死掉。这对于网站来说,是难以容忍的。而多进程模式下,一个处理请求的进程死了就死了,不会影响到网站服务主进程。从这个角度来看,CGI的多进程模式还是一种优点了。这真是,风水轮流转,老树发新枝。
最后,我们再来看db server(数据库服务器)层。由于数据库中装的全都是数据,而且是随时可能会改变的数据,而且是随时可能会变的海量数据。这是一个极为庞大的状态。这种状态几乎是不可能即时复制和传输的。因此,db server是最难扩展的。通常来讲,db server只有一台。最多还有另一台备份数据库,提供一些旧数据的只读服务。
在我看来,数据库集群的发展方向不在于即时复制和传输状态,而在于分布式存储管理。即数据分区域存放到不同的数据库服务器上。但是,这无形中就增加了数据库表格关联查询的难度,从而增大了数据库管理员和数据库应用程序员的工作难度。
相关标签: 应用服务器 web