【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

Ruby/Rails: 不一样的'Web'应用

  • 2008-09-02
  • 本文字数:4569 字

    阅读完需:约 15 分钟

从一个有趣的项目说起

近些年来,在 Web 开发领域发生了许多有趣的变化,涌现出大量的框架,使得快速开发 Web 应用程序变成现实。其中 Ruby on Rails 尤其引人注目。Ruby 的强大语法和表达能力配合 Rails 的思想,不仅创造了 Web 开发效率提升数倍的奇迹,也为非应用 Web 技术解决非传统 Web 领域的问题提供了一个很好的契机。

现在我就来介绍一个刚刚结束的有趣的实际应用项目(暂且称之为 W 项目)。W 项目是一套用于农场的自动化系统。该系统中包含了众多工业设备,如用于工人们佩 戴的移动 W 设备,RFID 数据收集设备(分散安装在农场各处),闸门控制设备,地磅电子称,显示屏…还有许多名目繁多的设备。这些设备有的通过电缆,有的通过 ZB(ZigBee)无线网络将数据汇集到一台工控服务器上。这台服务器负责收集和处理所有设备传回来的数据,并发送指令给相关设备,例如控制闸门。

系统中大部分设备都是可以直接采购到的产品,但还是有几个设备是需要定制开发,其中最重要的定制设备,就是 W 设备。W 设备可以看作是一个工人佩戴在手臂上 的移动 PDA。由于工作环境恶劣,W 设备与普通的 PDA 有很大差别,它只有很小的显示屏,数个按钮,内部配有 RFID 识读器,并且通过 ZB 无线网络与服务 器通讯,外壳坚固并可防水。

由于与客户沟通顺畅,该项目的开发工作进行得非常顺利。系统的软件部分集中在服务器,服务器软件的主要任务是:

  • 从众多设备采集数据,处理数据,控制设备。
  • 提供数据浏览,统计报表等功能。

服务器运行 Debian,用 Ruby On Rails 来完成第 (2) 项任务,用 Ruby 配上小部分 C 扩展来完成第 (1) 项任务。

W 设备上的嵌入式软件很简单,基本上就是采集数据,并通过 ZB 网络将数据发送到服务器,显示一些简单的信息等。

系统很快投入试点使用,运行良好。

变化 / 挑战

由于试点应用很成功,客户很快就有了把这套系统作为产品推广的想法,因此二期工程随即上马。

二期工程的性质发生了变化,由仅供自家用的“专用系统”要发展为一个“通用的产品”。由此带来的一个显著变化是客户为 W 设备赋予了更多更重要的角色。现 在,W 设备上要完成许多比以前复杂得很多的功能,并且要求日后能够方便地对 W 设备的功能进行定制(二次开发),以快速适应不同农场的需要。然而 W 设备是一 个资源非常有限的嵌入式系统,仅有数十 KB 的内存,各种外设的驱动加上 ZB 通讯协议棧已经消耗掉了 80% 的资源,按照原有架构去实现大量新功能已经不可行 了,然而维持现有硬件设备不增加硬件成本是项目的一个关键目标…又要马儿跑又要马儿不吃草?

我们来看看面临的挑战:

  • 增加很多复杂的操作界面 (超出了 W 设备的现有资源能力)
  • 功能变化快
  • 需要日后可定制功能 (二次开发)
  • 维持低成本 (意味着维持现有硬件架构不变)

解决这些问题最有效的方法就是把计算转移到服务器。所幸的是 W 设备和服务器是通过 ZB 无线网络实时连接的,这就为透过网络转移计算创造了条件。

解决方案

最经典的基于服务器端的解决方案莫过于传统的“UNIX 终端”模式,而且 ZB 无线网络窄带宽低延时特性似乎与终端模式可以很好地匹配。

但是要想直接应用“UNIX 终端”模式也有一些问题:

  • 服务器端编程比较复杂(例如基于 cursor/ncursor 库编程), 日后要进行二次开发效率低而培训成本会很高。
  • 在 W 设备上实现标准 Terminal Emulator 比较困难,有可能要为 W 设备增加内存而修改硬件设计。

提到终端,我不禁想起 DHH 在 RailsConf 2007 上的那个 keynote,他把浏览器和 IBM 3270 做了有趣的对比。是的,那是个绝妙的对比,它给我留下的印象远大于对 Cargo Cult 调侃。浏览器和终端本质上要解决的是同一个问题。不同的是,由于 web 技术取得长足的发展,在服务器端开发 Web 程序比开发终端模式的应用程序要 方便快捷得多。Rails 正是其中一个可以支持快速开发的绝佳例子。对这个项目而言,更重要的是服务器已经在跑 Rails 了,继续用 Rails 作为基础架 构将会节约很多资源。

那么客户端呢?与实现“Terminal Emulator”相比,实现“Web Browser”难度更大。但是,仔细地去考察浏览器,复杂的原因在于 HTML 多媒体渲染以及客户端脚本。文本 Web 浏览器是可以相当小巧的。W 设备并不 需要华丽的界面。而且由于 HTTP/HTML 效率太低并不合适 ZB 网络的低带宽,定制传输协议和标记语言势在必行。新的自定义的标记语言相当简洁(我们称 之为 MML:Micro Markup Language),在 W 设备中实现对应的“浏览器”变得异常轻松,最终只用了大约 2k 行左右的 C 代码。

再回到服务器端,如何使 Rails 适应这些定制的协议和标记语言?

从外部来看,Rails 提供了以下主要服务:

  • MVC 编程架构
  • 透过 ActiveRecord 与数据库打交道
  • 为 HTML 渲染提供服务
  • 其他如测试,数据迁移,插件…等等

其中份量最重的 ActiveRecord 部分与 web 其实完全无关,可以“拿来就用”。很多便利工具,例如测试,数据迁移,插件机制等等,其实与 web 也无多大关系。

既然 Rails 的 MVC 中,M 与 web 无关,C 部分主要留给业务逻辑,而 V 部分对于非 web 领域价值不大,倘若要基于 rails 再建一个领域特定的 MVC,工作量也就是集中在 V 部分了。而这个 V 部分,既然是领域相关,则无论采用什么方案都是一个不可避免的工作。由于定制的 MML 是一个非常简单的标记 语言,因此 V 部分也相当简单。当我们把 Rails 的思想与习惯用法再应用到这个新的 MVC 上时,就得到了一个基于 Rails 并且与 Rails 神似的框架。 我们可以称这种框架为“领域特定的框架”(Domain Specific Framework,DSF)。

归纳起来,解决方案就是:客户端使用定制的 MML 展现数据,服务器端为基于 Rails 的 DSF,这样可以满足客户的所有要求,并且具有良好的可扩展性。

实现基于 Rails 的 DSF

要基于 Rails 来实现这样一个 DSF 以适应非传统 Web 应用,有两个途径:一是对 Rails 的各个部分进行修改,例如修改 router 以适应新的协议,修改 render 适应 MML 等等;二是利用 Rails 的现有设施,按照 Rails 的思路重新构造某些部件。

第一种方法实施起来并不容易。虽然使用 Rails 容易,而 Rails 本身是比较复杂的,修改起来并不容易,另外还享受不到 未来 Rails 升级的好处。而第二种方法除了能够享受未来 Rails 升级的好处外,还可以与现有的 Rails 程序和平共处,并且无缝连接,因此选择后者来 实现。要实现 full stack 的 MVC framework,除了直接利用 Rails 的 ActiveRecord 之外,还需要实 现:Parser,Router,Server,Controller 和 MML render。

Parser: 负责解析自定义的通讯协议,获取从 W 设备传来的请求,并解析参数等。

Router: 扫描并装载 Controllers,缓存 Controller 对象,根据 Parser 的结果取得相应 Controller 的对象。Router 还负责监控 Controller 是否已被修改和重新装载 Controller,这样就可以和 Rails 一样,在开发的时候可以立即看到修改的结果而不用重启服务器。

Server: 总控制,从串口中读取 ZB 网络数据,调用 Parser 解析, 把结果传给 Router,从 Router 中获取 Controler 对象并根据 Parser 结果调用 Controller#Action,以及缓存 Controller 的输出等等。

Controller: 用户应用的业务逻辑都放在 Controller 的子类里实现。在 Controller 里直接调用 rails 的 Models 访问数据库。

MML Render: 使用 erb 作为模板文件,再加上一些辅助的功能,例如 render link,menu 之类的,和自定义的 MML 特性密切相关。MML Render 作为 module 最终 mixin 到 Controller 里面。

从上面各个模块的功能描述可以看出,这个 DSF 模型几乎和 rails 是一样的,但由于是面向自定制的协议和 MML,其复杂度和实现难度大大低于 Rails,再加上 Ruby 语言的强大表达能力,最终这个 DSF 仅用了不到千行代码!

再来看看在这个 DSF 下开发应用程序会是怎样的,以一个最简单的"Hello World"为例:

contollers/main.rb:<br></br>Ruby 代码:<br></br> class MainController < WSController<br></br> controller_map_to :m<br></br> action_maps :index => "i"<p> def index</p><br></br> @text = "Hello world"<br></br> end<br></br> end<p> views/main/main_index.erb:</p><br></br> Ruby 代码:<br></br> <%= "<p3.20crs2e3.5> #{@text}" %>在 MainController 中的 controller_map_to 起的作用是把自己(main)映射到一个较短的名字"m",而 action_maps 则对 actions 取短的别名(本例中,index 的别名是 i),这样做的目的是为了减少请求串的长度。(ZB 网络的带宽非常有 限,节约每一个字节意义都很大)。

再看看 view,其中“<P3.20CrS2E3.5>”表示在第 3 行 20 列处 (P3.20),以红色 (Cr)2 号字 (S2) 显示 @text,经过 3.5 妙后清除屏幕 (E3.5)。当然,如果想更方便地描述这些 MML 属性,则可以定义一系列 helper 函数,或者干脆定义一套 DSL。

这个简单的例子没有演示 Models,因为它可以直接使用 Rails 的 Models,因此使用起来和在 Rails 中没有丝毫差别。例如可以使用 has_many,belongs_to 等等。

通过这个例子,我们可以体会到这个 DSF 与 Rails 有多么“神似”,熟悉 Rails 的人通过几分钟简单的了解就可以立即在这个新的 DSF 下开发应用。二次开发的问题迎刃而解。

结论

当我们把 MVC Web 框架的概念推广到 web 之外,那么这个 V 就可以是任意的领域特定的数据展示格式。它既可以是基于文本的,也可以是基于二进制的;既可以是自定义的, 也可以去兼容已有的格式。通过定制的 DSF 来解决问题不是没有意义的“重复造轮子”,而是解决领域特定问题的一个有效手段。而基于 Rails 来实现 DSF 更是有着非常显著的优势,整个复杂的 Model(ActiveRecord)可以不经任何修改而直接利用,所需要的代价仅仅是在 DSF 里面增加一行代码:

require File.dirname(__FILE__) + '/../config/boot'Rails 中的众多优秀工具例如数据迁移,测试,调试,插件等等,大部分也可以直接使用,可以说基于 Rails 来实现 DSF 只需要付出 5%的努力,就可以达到 100% 的效果。

当遇到需求变化时,运用恰当的技术手段有时候可以柳暗花明,特别是跨领域交叉应用,往往能收到意想不到的效果。web 技术的蓬勃发展带来了异彩纷呈的诸多 框架技术,开发工具,以及丰富的人才储备,这些资源对于非 Web 领域也有巨大的吸引力。本文所举的这个例子就是巧妙地通过基于 Rails 的 DSF 来解决实 际问题。实际上这个例子还有一个精彩的插曲值得一提,那就是客户希望可以脱离 W 设备和 ZB 网络来开发应用程序,简单地说,就是希望有一个 W 设备的硬件模拟 器。在传统解决方案里面,硬件模拟器是一项非常复杂的工作,但在这里,由于整个解决方案采用的是 Web 技术,因此实际上模拟器的核心就是一个简单的 MML 到 HTML 的转换程序加上少许 JavaScript 而已,浏览器就摇身变成了一个硬件模拟器。突破传统思维的束缚,就容易找到金矿。

我不是一个 Web 程序员,也从未开发过用户超过十个人的传统 Web 程序,但这并不意味着 Web 技术对我无用。正相反,Web 技术经常被应用到我所从事的嵌入式系统领域。基于 Rails 的 DSF 解决方案为加速 Web 技术在其它领域的应用开启了一道光明之门。

作者简介:郑功梓,资深潜入式系统工程师,技术涉猎广泛,前新大陆自动识别技术有限公司总工程师,现旅居新西兰。


志愿参与 InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com 。也欢迎大家到 InfoQ 中文站用户讨论组参与我们的线上讨论。

2008-09-02 21:021411

评论

发布
暂无评论
发现更多内容

dapp软件开发 智能合约项目定制

西安链酷科技

区块链 软件开发 dapp 去中心化 交易所

超2000个大模型应用,支持文心4.0!AI Studio星河大模型社区升级上新

飞桨PaddlePaddle

飞桨 AI Studio 星河社区 文心大模型4.0

“敏捷教练进阶课程”12月2-3日 · A-CSM认证在线周末班【分时段模块化教学】CST导师亲授

ShineScrum捷行

如何选择安全又可靠的文件数据同步软件?

镭速

数据实时同步

大模型训练中的AI合成数据应用

百度开发者中心

大模型 人工智能「 LLM

华为云GaussDB城市沙龙活动走进安徽,助力金融行业数字化转型

华为云开发者联盟

数据库 后端 华为云 华为云GaussDB 华为云开发者联盟

酷克数据出席永洪科技用户大会 携手驱动商业智能升级

酷克数据HashData

证券开源领航者!国金证券通过中国信通院可信开源治理“先进级”评估

新消费日报

用 Milvus 和 NVIDIA Merlin 搭建高效推荐系统

Zilliz

nvidia Milvus Zilliz 向量数据库

Hadoop RPC简介

数新网络官方账号

大数据 hadoop hadoop rpc

多模态对比语言图像预训练CLIP:打破语言与视觉的界限

汀丶人工智能

人工智能 自然语言处理 计算机视觉 GPT 多模态大模型

如何选择最适合你的香港服务器服务?五大优势你不可不知

一只扑棱蛾子

香港服务器

Hazelcast IMDG 概览

数新网络官方账号

数据库 #数据库

Privatus for Mac(网页缓存清理) 6.6.2永久激活版

mac

苹果mac Windows软件 Privatus 网页缓存清理软件

HDFS架构介绍

数新网络官方账号

大数据 hdfs 架构-

行云创新加入深圳市人工智能行业协会

行云创新

AI编程 人工智能协会 行云创新加入人工智能协会 云原生+AI 云端IDE+大模型

CAEE2023 | 造物云×华为云共建电子电路智慧云工厂,引领产业创新发展浪潮

Geek_2d6073

中企出海 | 中建材、红狮、华润、华新都在做的事儿!

用友BIP

中企出海

ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑

汀丶人工智能

Elastic Search 搜索系统

深入理解 MySQL 中的锁和MVCC机制

这我可不懂

MySQL MVCC

独家特性 | 腾讯云大数据ES:一站式索引全托管,自治索引大揭秘!

腾讯云大数据

权重修改与预训练模型的应用

百度开发者中心

人工智能 大模型

星环科技分布式向量数据库Transwarp Hippo正式发布,拓展大语言模型时间和空间维度

星环科技

聊聊 Rust 变量,你学会了吗?

树上有只程序猿

rust

EasyDL平台的强大开发力量

百度开发者中心

大模型 #人工智能

微服务之负载均衡使用场景

互联网工科生

负载均衡 微服务

企业通关必备,iPaaS应该这样搭建

RestCloud

应用集成 ipaas 应用与数据集成

用友BIP数智干部管理——数管干部 人才强企

用友BIP

数智干部管理

1.从零开始学Windows批处理编程系列之基础介绍

全栈工程师修炼指南

编程 windows 批处理 运维学习之路

百度AICA首席AI架构师培养计划第七期毕业,大模型深入产业见成果

飞桨PaddlePaddle

架构师 大模型 AICA

Databend 开源周报第 117 期

Databend

Ruby/Rails: 不一样的'Web'应用_Ruby_郑功梓_InfoQ精选文章