在上一部分的文章中,我们深入了解了Web在基础层面是如何工作的,其中包括客户端(你的电脑)与服务器(另一台响应客户端请求网页的电脑)交互。
 
在这篇文章——四篇文章中的第二篇——我们一起来了解客户端,服务器以及基本Web应用程序的其它部分如何配置,才使得浏览网页的体验成为可能。
 

客户端-服务器模型

客户端与服务器跨越网络通信的概念被称为“客户端-服务器”模型,这使得浏览网站(如你查看该文章)和与Web应用程序(如GMail)交互成为可能。
 
客户端-服务器模型实际上只是描述客户端与Web应用程序服务器之间给予-获取关系的一种方式——就像你可能使用“男朋友”和“女朋友”来描述你的个人关系一样。这是信息如何从一端到另一端的细节,从而使得这个过程看起来很复杂。
 

一个基本的Web应用程序配置

配置Web应用程序有很多种方式,也就是说,绝大部分的方式都遵循着同样的基本结构:客户端、服务端和数据库。
 

客户端

客户端是与用户交互的,所以,客户端代码主要负责用户实际看到的大部分功能。这包括:
  1. 定义网页的结构。
  2. 设置网页的样式。
  3. 响应用户的操作(如点击按钮、输入文字等等)
 
结构:你网页内容呈现及布局是由HTML来定义的(如今大部分Web程序用的是HTML5,当然其它的就另说。)
 
HTML表示超文本标记语言,它允许你使用HTML标签来描述文档的基本物理结构,文档中每一个HMTL标签都描述了一个特定的元素。比如:
 

  • “<h1>”标签内的内容描述的是头部。
  • "<p>"j标签内的内容描述的是一个段落。
  • "<button>"标签内的内容描述的是一个按钮。
  • 等等……
 
网页浏览器使用这些HTML标签来决定如何呈现这个文档。
 
样式:用来定义网页的样子,Web开发人员使用CSS(层叠样式表)来定义样式。CSS是一种用来描述你的HTML文档中的元素的样式的语言,它允许改变字体、颜色、布局、简单的动画,和其它表面元素。
 
你可以为上面的HMTL页面设置样式,如下图:
 
 

用户交互:最后,JavaScript来处理用户交互。

 
比如,如果你想当用户点击的你按钮时做一些事情,你可能会这样做:
 

如上面这样的用户交互,是在还没有到达服务器就可以处理的交互,这种用术语来说就是“客户端JavaScript”。其它的交互需要你发送请求至服务器有服务器处理。

 
比如,如果用户在一个线程里发布了一条评论,你可能想把它存储在你的数据库,把所有分散的信息组织起来保存在同一个地方。所以,你发送一个包含新的评论和用户ID的请求至服务器,服务器会侦听这些请求,并相应地处理它们。
 
我们在这一系列文章的下面一部分会更加深入地探究HTTP请求-响应。
 

服务器

Web应用程序服务器会侦听来自于客户端的请求,当你建立了HTTP服务器,你会设置一个侦听端口号。端口号总是与电脑IP地址联系在一起的。
 
你可以认为端口是每天电脑分隔的一个通道,这些通道可以来执行不同的任务:一个端口可以被用来浏览www.facebook.com,同时另一个端口用来获取你的邮件。电脑能同时做这两件事,是因为每个应用程序(网页浏览器和邮件客户端)使用了不同的端口号。
 
一旦你搭建了HTTP服务器来侦听特定的端口,那这台服务器就会等待客户端通着这个端口来的请求,并执行请求的任何操作,同时通过HTTP响应报文发送被请求的数据。

数据库

数据库是Web架构中的基底——大部分的人都害怕去探究它,但是它们是一个结实基础评判标准。数据库是用来存放信息的地方,因此你可以轻易地访问、管理和更新它们。
 
比如说,如果你正在建立一个社交媒体网站,你可能使用数据可存储关于你的用户信息、文章、评论。当一个访客请求一个页面,这个页面的数据就是来自你网站的数据库,允许实时用户交互,就像我们在如Facebook或像Gmail的应用中功能一样理所当然。

这些可以说是全部的内容了

就像上面说的一样简单。我们刚刚介绍了一个Web应用程序的所有基本功能。
 
 

如何扩展一个简单的Web应用程序

上面的配置对于简单的应用程序已经够了,但是应用程序功能扩大,一台服务器没有能力去同时处理数千个来自访客的请求。
 
为了处理这么多请求量,我们能做的就是分发请求流量给一个后台服务器群。
 
在这里就使得事情变得很有趣了。你有多台服务器,每台服务器都有各自的IP地址,那么域名服务器(DNS)如何知道要把你的流量发送到哪个应用程序实例?
 
简单的答案是DNS不知道。管理所有独立的应用程序实例是通过一个叫负载均衡器来做到的。
 
负载均衡器扮演交警的角色,它把客户请求以尽量快而有效的方式传送给服务器。
 
由于你不能广播你所有服务器实例的IP地址,你创建一个虚拟IP,把这个IP地址公开给所有客户端,这个虚拟IP指向你的负载均衡器,所以当DNS查询你网站的IP时,它将指向负载均衡器的IP,然后负载均衡器再实时分发流量给每台后端服务器。
 
你可能会想负载均衡器如何知道应该把流量发送至哪台服务器,答案是:算法。
 
一种流行的算法是轮询,它均匀地分布所有请求给你的服务器群(所有可用的服务器)。如果你所有的服务器处理速度和内存一样的话,你通常会选择这种方式。
 
另一种算法是根据最少连接数来决定下一个请求发送给最少活动连接数的服务器。
 
根据你的需要,你可以从很多算法中选择一种来应用。
 
这个流程类似于下面这样的:
 

服务

我们通过创建服务器池和负载均衡来管理它们解决了我们的流量问题,一切都进行得不错,对吗?
 
……但是随着你应用程序的增多,只是增加服务器还是会导致一些问题。随着你的应用程序添加更多的功能,而且以后还会添加,这样你得一直维护这同一服务器。为了解决这个问题,我们需要一种方式来解耦服务器功能。
 
这就是服务出现的缘由,一个服务是另一台服务器,区别是它只与其它服务器交互,而不是直接与客户端交互的传统Web服务器。
 
每个服务都包含一个独立的功能,比如用户授权或者提供搜索的功能。服务允许你将单台Web服务器拆分为多个服务,每个服务执行不同的功能。
 
将单台服务器拆分为多个服务的主要好处是,允许你完全独立地扩展服务。
 
这样做的另一个优势是,允许公司开发团队各自去开发部分服务,而不是10个,100个,甚至1000个工程师开发同一台服务器的应用,如果这样很快成了项目管理的噩梦。
 
请注意:当你的应用程序部署在越来越多的服务器集群上时, 负载均衡、后端服务器集群,以及服务的概念变得越来越有挑战性。如会话持久化这样的事变得特别棘手——例如,如何在会话期间从客户端发送多个请求到同一个服务器的——以及如何部署你的负载均衡方案。在本文我们暂时不谈论这些高级的话题。
 

内容分发网络

以上所有的工作能很好的扩展流量,但是你的应用却一直集中在一个地方,当你的用户在你国家的其它地方或者其它国家访问你的网站,他们的网页加载可能要很长时间,因为这是由于客户端和服务器相隔太远造成的。毕竟我们谈论的是“万维网”,而不是“本地Web”。

解决这个流行的策略是使用内容分发网络(CDN),CDN是一个大型“代理”服务器分布式系统,它部署在多个数据中心。代理服务器只是一个扮演客户端与服务器的中间服务器。
 
有大量分散流量的公司可以选择付费CDN公司来分发它们的内容给终端用户。比如Akamai就是一个CDN公司,Akamai拥有成千上万台服务器,它们部署在世界各地有战略性的地理位置。
 
让我们来比较在有CDN和没有CDN的情况下浏览网页是如何进行的。
 
就像我们在第一部分谈论的传统网站,URL中的域名转换成主机服务器的IP地址。
 
然而,如果一个公司的网站使用了Akamai,URL中的域名会转换成Akamai公司下的服务器的IP,然后Akamai把网站内容传送给浏览这网站的使用者,这样使用者甚至不用连接该公司的服务器。
 
Akamai可以从其客户的服务骑上获取并保存那些经常被使用的元素,比如HTML、CSS、软件下载和媒体文件。
 

这样做的主要目标是使得你的网站内容离使用者更近,如果用户请求的内容不用通过很远的地方去获取,那这样意味着更低的延迟,这也就降低了网页的加载时间。

 
在下一篇文章中,我们将更进一步探讨HTTP和REST。

(译)Web是如何工作的(2):客户端-服务器模型,以及Web应用程序的结构的更多相关文章

  1. (译)Web是如何工作的:给Web开发新手的初级读物

    原文地址:https://medium.freecodecamp.org/how-the-web-works-a-primer-for-newcomers-to-web-development-or- ...

  2. (译)Web是如何工作的(3):HTTP&REST

    原文地址:https://medium.freecodecamp.org/how-the-web-works-part-iii-http-rest-e61bc50fa0a   我们在第一篇文章中介绍了 ...

  3. Web服务器的工作原理

    Web服务器的工作原理 Web服务器工作原理概述 很多时候我们都想知道,web容器或web服务器(比如Tomcat或者jboss)是怎样工作的?它们是怎样处理来自全世界的http请求的?它们在幕后做了 ...

  4. Web Service 的工作原理

    Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...

  5. ASP.NET Web Service如何工作(3)

    ASP.NET Web Service如何工作(3) [日期:2003-06-26] 来源:CSDN  作者:sunnyzhao(翻译) [字体:大 中 小] 为了使.asmx句柄有可能反串行化SOA ...

  6. 【译】使用Jwt身份认证保护 Asp.Net Core Web Api

    原文出自Rui Figueiredo的博客,原文链接<Secure a Web Api in ASP.NET Core> 摘要:这边文章阐述了如何使用 Json Web Token (Jw ...

  7. Web Service 的工作原理(转载)

    Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...

  8. 【转载】Web Service 的工作原理

    http://www.cnblogs.com/Jessy/p/3528341.html Web Service基本概念 Web Service也叫XML Web Service WebService是 ...

  9. 【JavaEE】Web Service 的工作原理

    Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...

随机推荐

  1. 微信小程序去除button按钮的边框

    小程序开发记录 小程序开发中, 有时候我们希望button不要有边框, 需要使用button::after来实现, 具体如下: .operations button::after{border:0 n ...

  2. iOS 开发人员不可缺少的75个工具

    原文出处: Ben Scheirman 译文出处: Njuxjy 假设你去到一位熟练的木匠的工作室,你总是能发现他/她有一堆工具来完毕不同的任务. 软件开发相同如此. 你能够从软件开发人员怎样使用工具 ...

  3. UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)

    题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...

  4. 转:MAVEN依赖的是本地工程还是仓库JAR包?

    相信大家都碰见过 maven 配置的依赖或者是 jar 包或者是工程,在开发的过程当中,我们当然需要引入的是工程,这样查看 maven 依赖的文件的时候,就能直接查看到源码. 一.本地工程依赖 举个例 ...

  5. 以KeyValue形式构建Lua Table

    Key为字符串 -- 定义一个key,value形式的table local kv = {fruit = "apple", bread = "french", ...

  6. TextMesh Pro Emoji Align With Text(表情和文字对齐)

    前言 MMO游戏中需要富文件组件,大体功能包括图文混排,表情,超链接,文字动画等富文本功能,且DC数占用少. 本文选择Unity免费提供的TextMesh Pro 解决方案. 软件环境 Unity3D ...

  7. java枚举细节

     1.在没有枚举之前,我们如果需要一些常量,比如说,我们想用一些常量来代替订单的几种状态,如已下单未付款.已付款未发货.已发货未确认收货.已收货未评价.已评价.我们会定义一个用来装常量的类,比如: p ...

  8. js、jquery实现模糊搜索功能

    模糊搜索功能在工作中应用广泛,并且很实用,自己写了一个方法,以后用到的时候可以直接拿来用了! 实现的搜索功能: 1. 可以匹配输入的字符串找出列表中匹配的项,列表框的高度跟随搜索出的列表项的多少改变 ...

  9. 「mysql优化专题」视图应用竟然还可以这么优化?不得不收藏(8)

    一.视图概述(技术文): (1)什么是视图? 视图是基于 SQL 语句的结果集的可视化的表. 视图包含行和列,就像一个真实的表.视图中的字段就是来自一个或多个数据库中的真实的表中的字段.视图并不在数据 ...

  10. 6.python内置函数

    1. abs() 获取绝对值 >>> abs(-10) 10 >>> a = -10 >>> a.__abs__() 10 2. all()   ...