Skip to content

四火的唠叨

一个纯正程序员的啰嗦

Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接
Menu

Web 页面的聚合技术

Posted on 04/11/201206/23/2019 by 四火

近接触到了 Mason,并且了解到了它基础之上的一个 MVC 框架实现,随即联想到做网站以来接触到的各种各样的页面聚合的场景,颇有意思。

页面聚合本身是一种 “分而治之” 的思想,把复杂的页面分割成可以被重用和独立维护的部分,这些部分的来源灵活,可以来自同一个 web app 中,也可以来自不同的域;可以聚合独立的子页面(页面集成),也可以聚合数据(数据集成),甚至可以聚合子呈现(模板集成)。

客户端聚合

这种聚合的最大好处在于把聚合的工作分散到如今越来越强势的客户端,减轻了服务端的压力;另一方面,也从一定程度上简化了服务端的设计。客户端聚合在互联网初期比较少见,如今随着客户端性能越来越优秀,客户端聚合的优势逐渐显示出来。

最简单的聚合形式:frame 聚合。请看谷百搜索。这种聚合形式的局限性在于,即便使用了 frame 标签,也依然是两个网站,那么两个子页面之间的交互就由于浏览器的安全限制变得困难。这是一种纯粹的静态聚合的形式,使用 HTML 的 include 标签亦类似。

客户端模板的聚合方式。例如 Velocity、FreeMarker 这些传统的模板技术,都可以做到客户端的聚合。一方面从服务端获取静态模板页,因为这些页面几乎是纯静态的,因此性能非常高;另一方面通过 ajax 技术从服务端获取变化的数据,优先展示主页面内容,优化页面展示体验,二者在页面上通过 JavaScript 的帮助形成最终的页面效果。

举例来说,比如服务端返回的模板片段是:

1
<div id="user.name">${user.name}</div>

再通过 ajax 从服务端获取到的页面数据是:

1
{user:{name:"Jim", age:"15"}}

聚合后的效果:

1
<div id="user.name">Jim</div>

例子非常简单,在这种模式下,对于变化数据的获取,可以使用 Node.js 接口来实现,并使用 JSON 作为数据传递形式,这个数据服务的子系统变成了一个完全独立于页面展示的数据服务提供者。

关于服务端推送技术:在页面聚合的过程中,有些数据实时性强,或者数据量大,无法一次获取完成,需要多次反复从服务端获取数据,而且,这部分数据产生的时间是由服务端确定的。看一看新浪微博、人人网,这些 SNS 网站中,都大量应用了这种技术。

服务端推送的方式有几种,而传统 BS 结构的特点是,数据都是去 “拉” 的,要服务端主动通知客户端需要绕一点点弯。

最简单的方式是轮询。客户端不断地 ajax 查询服务端(例如每隔 1 分钟查询一下是否有新的数据),甚至不断刷新页面或者子页面。但是这样的办法存在一个问题,就是大量的查询请求很可能是浪费掉的,例如一小时在线用户,每分钟 ajax 查询一次数据,查询了 60 次,只有一次是有数据的,那么剩余 59 次都是白白浪费的。

还有一个办法是被称为 “Long Pulling”(例如 pushlet 技术),服务端在接收到客户端的 ajax 查询请求时,如果没有数据,不要返回,而是 hold 住这个 HTTP 连接,直到有数据了再返回。这里的好处显而易见,但是问题也很明显——大量的连接,因此在这种情况下,多路复用技术(可以参考 NIO Server 的材料,也可以参见这里)就显得格外有用了。

第三种办法采用的比较少,就是采用第三方控件,比如Applet、ActiveX 等控件,和服务端交互,他们的交互可以超越网页传统的模型,甚至支持非 HTTP 的协议,由服务端主动推送数据。

服务端聚合

服务端聚合的本地模板聚合是最传统的聚合形式,是页面重用的基础,由模板引擎解析运算模板为最终的页面,写入输出流。这里以 SiteMesh 举例:

配置一个 url mapping 文件,再在模板上使用 SiteMesh 标签:

1
2
3
<div class='mainBody'> 
  <sitemesh:write property='body'/> 
</div>

SSI:服务器端嵌入(Server Side Include),这也是为什么很多老网站的 URL 都是以.stm、.shtm 或.shtml 结尾的。它的嵌入和 html 标签里面的 include 不一样,SSI 是为 WEB 服务器提供的一套命令,这些命令只要直接嵌入到 HTML 文档的注释内容之中即可生效,但是它的解析需要特定的服务器支持。

1
<!--#include file="extend.htm"-->

随着页面缓存在互联网应用世界的称王,Oracle 定义了ESI作为一种缓存方式聚合页面的规范,它规定了将 Web 网页的页面的片段进行缓冲/缓存的技术方式。

1
<esi:include src="http://example.com/1.html" alt="http://bak.example.com/2.html" onerror="continue"/>

Portlet 聚合。Portlet 在早几年的企业门户应用中很常见,它本身是一组规范,也规定了一种聚合页面的方式,可以远程聚合,也可以本地聚合,它可以协助应用将数据实体和展现模板在组网上就分离开,业务节点部署可以非常灵活,Portlet 是网站解耦的一大利器。

Portal 使用 portlet 作为可插拔用户接口组件,提供信息系统的表示层。作为利用 servlets 进行 web 应用编程的下一步,portlets 实现了 web 应用的模块化和用户中心化。portlet 规范,即 jsr(Java Standardization Request)168,是为了实现 portal 和 portlet 的互操作。它定义了 portlet 和 portlet 容器之间的合约,让 portlet 实现个性化、表示和安全的 api 集。规范还定义了怎样在 portlets 应用中打包 portlets。

jsr168 的目标是:

定义 portlet 的运行时环境,即 portlet 容器

定义 portlet 和 portlet 容器之间的 api 集

提供 portlet 存储易失数据和持久数据的机制

提供 portlet 包含 servlet 和 jsp 的机制

定义方便部署的 portlet 打包方法

提供 jsr168 规范下的 portal 的二进制 portlet 便携性

通过 WSRP(web service for remote portlet)协议运行符合 jsr168 规范的远程 portlet

将复杂的页面代码交给程序开发人员进行处理,以降低网页设计的难度

假设我是一个 intranet 网站的管理员,我的公司买了一个能显示新闻信息的第三方 portlet 应用,该应用允许用户指定跟踪新 闻更新的 URL 地址,我想借助它为用户显示公司的内部新闻。另一个需求是我不想让用户通过该应用来跟踪任何其它的新闻信息来源。作为管理员,我可以为所有 的用户指定一个用于内部新闻更新的 URL 地址,同时通过改变 portlet 应用的部署描述符来取消其它人修改该地址的权限。

Portlet 就能实现这一需求,Portlet 是由 Portlet 容器聚合的,用户看到的是一个单一和完整的页面,他并不了解页面中的一个个 portlet 栏目到底来自何方。

Portlet 页面组装过程:

Portlet 由于在聚合中采用了两次请求转发的方式(一次 Action 请求、一次 render 请求),导致效率天然不高。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

×Scan to share with WeChat

你可能也喜欢看:

  1. 大型互联网应用的技术选型和决策,10 条成功与失败的记录
  2. 网站性能优化的三重境界
  3. 互联网数据聚合
  4. 程序员,都去写一写前端代码吧
  5. CommonJS

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

订阅·联系

四火,啰嗦的程序员一枚,现居西雅图

Amazon Google Groovy Hadoop Haskell Java JavaScript LeetCode Oracle Spark 互联网 亚马逊 前端 华为 历史 同步 团队 图解笔记 基础设施 工作 工作流 工具 工程师 应用系统 异步 微博 思考 技术 数据库 曼联 测试 生活 眼界 程序员 管理 系统设计 缓存 编程范型 美股 英语 西雅图 设计 问题 面向对象 面试

分类

  • Algorithm and Data Structure (30)
  • Concurrency and Asynchronization (6)
  • System Architecture and Design (43)
  • Distributed System (18)
  • Tools Frameworks and Libs (13)
  • Storage and Data Access (8)
  • Front-end Development (33)
  • Programming Languages and Paradigms (55)
  • Testing and Quality Assurance (4)
  • Network and Communication (6)
  • Authentication and Authorization (6)
  • Automation and Operation Excellence (13)
  • Machine Learning and Artificial Intelligence (6)
  • Product Design (7)
  • Hiring and Interviews (14)
  • Project and Team Management (14)
  • Engineering Culture (17)
  • Critical Thinking (25)
  • Career Growth (57)
  • Life Experience and Thoughts (45)

推荐文章

  • 谈谈分布式锁
  • 常见分布式系统设计图解(汇总)
  • 系统设计中的快速估算技巧
  • 从链表存在环的问题说起
  • 技术面试中,什么样的问题才是好问题?
  • 从物理时钟到逻辑时钟
  • 近期面试观摩的一些思考
  • RSA 背后的算法
  • 谈谈 Ops(汇总 + 最终篇):工具和实践
  • 不要让业务牵着鼻子走
  • 倔强的程序员
  • 谈谈微信的信息流
  • 评审的艺术——谈谈现实中的代码评审
  • Blog 安全问题小记
  • 求第 K 个数的问题
  • 一些前端框架的比较(下)——Ember.js 和 React
  • 一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js
  • 工作流系统的设计
  • Spark 的性能调优
  • “残酷” 的事实
  • 七年工作,几个故事
  • 从 Java 和 JavaScript 来学习 Haskell 和 Groovy(汇总)
  • 一道随机数题目的求解
  • 层次
  • Dynamo 的实现技术和去中心化
  • 也谈谈全栈工程师
  • 多重继承的演变
  • 编程范型:工具的选择
  • GWT 初体验
  • java.util.concurrent 并发包诸类概览
  • 从 DCL 的对象安全发布谈起
  • 不同团队的困惑
  • 不适合 Hadoop 解决的问题
  • 留心那些潜在的系统设计问题
  • 再谈大楼扔鸡蛋的问题
  • 几种华丽无比的开发方式
  • 我眼中的工程师文化
  • 观点的碰撞
  • 谈谈盗版软件问题
  • 对几个软件开发传统观点的质疑和反驳
  • MVC 框架的映射和解耦
  • 编程的未来
  • DAO 的演进
  • 致那些自嘲码农的苦逼程序员
  • Java 多线程发展简史
  • 珍爱生命,远离微博
  • 网站性能优化的三重境界
  • OSCache 框架源码解析
  • “ 你不适合做程序员”
  • 画圆画方的故事

近期评论

  • panshenlian.com on 初涉 ML Workflow 系统:Kubeflow Pipelines、Flyte 和 Metaflow
  • panzhixiang on 关于近期求职的近况和思考
  • Anonymous on 闲聊投资:亲自体验和护城河
  • 四火 on 关于近期求职的近况和思考
  • YC on 关于近期求职的近况和思考
  • mafulong on 常见分布式基础设施系统设计图解(四):分布式工作流系统
  • 四火 on 常见分布式基础设施系统设计图解(八):分布式键值存储系统
  • Anonymous on 我裸辞了
  • https://umlcn.com on 资源链接
  • Anonymous on 我裸辞了
© 2025 四火的唠叨 | Powered by Minimalist Blog WordPress Theme
Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接