前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源服务器端软件的接口风格和分歧

开源服务器端软件的接口风格和分歧

作者头像
韩伟
发布2018-03-05 16:09:43
1.3K0
发布2018-03-05 16:09:43
举报
文章被收录于专栏:韩伟的专栏韩伟的专栏

前言

开源运动风起云涌,现在已经成为IT技术最重要的表现形式。从早期的GNU运动,到Apache基金会项目,到GitHub,开源项目已经几乎覆盖了全部的较通用的软件领域,以及非常多的专用业务领域。一般来说,每个软件的设计都是独特的,其使用接口也是非常多样化的,所以对于开源软件的使用者来说,通常都会碰到所谓“易用性”问题——他们需要花大量的时间去阅读开源软件的使用文档、实例代码,最典型的就是诸如《Linux环境编程》这种书,很少有低于300页的篇幅。不过,在过去的十几年,开源项目在易用性的问题上,渐渐走出了一条新路:越来越多的开源软件,在用户使用界面上,采用了趋同的接口标准。尽管这些渐渐相似的接口标准,在性能上、功能完备性上可能并不是最优的选择,但是这种标准和接口的趋同,大大降低了用户对开源软件学习的难度。本文希望通过七个最常见的服务器端的这种趋同技术取向来阐述,希望能对新的开源项目的技术选择提供一些参考。

TCP/IP协议

TCP/IP协议作为互联网的基础通信协议,其“影响力”无与伦比。但是现在我所说的并不是其在一般通讯上的能力,而是关注其作为服务器端进程间通信的手段。一般来说,进程间通信我们往往有比TCP/IP更好的手段,比如在windows上我们有windows消息机制;我们还有共享内存、Linux的信号机制、管道机制、甚至我们还可以用IPX协议。

从性能和编程便利性上来说,使用windows消息机制、共享内存,往往都会比TCP/IP的使用更好。而管道和信号机制,对于特定模式下的通信,也会比TCP/IP更简单。然而,这些都没什么用,因为TCP/IP是在所有操作系统、所有语言、平台都支持的,这让越来越多的开源项目,把TCP/IP作为一个“标准”的进程间通信方式。

开源项目举例来看:

1. MySQL使用一个tcp的地址和端口来提供SQL服务,这和传统的ODBC配置,使用一个“数据库名字”更容易被诊断。

2. Tomcat提供了两个TCP地址,一个用于接受来自Apache的请求转发,一个用于直接HTTP访问。这比CGI规范的stdin/stdout更简单明白。

3. ActiveMQ提供一个TCP地址,用于接受消息终端进程的读写请求。

4. ZooKeeper提供TCP地址作为接入端

这个列表还可以很长,除了使用TCP端口外,部分软件还会使用UDP端口,但是由于进程间通讯往往需要保证数据到达和顺序,所以用UDP的较少一些。

URL描述符

在我们开发一个函数、一个服务的时候,我们往往会需要提供一种描述资源的方式给用户,比如在磁盘上的一个文件,网络上的一个服务,集群中的一个进程,甚至直接就是一个集群。在早期的开源项目中,如何“描述”一个资源可谓五花八门,最典型的描述方法就是类似文件目录路径的斜杠法区分;也有很多使用一个简单的数字ID来描述的,比如Linux中无所不在的各种描述符。IP地址也是一种常见的描述符,用4段0-255组成的一个32位数字。

在互联网用户普及的过程中,URL实际上是作为最初的概念,得以深入人心的。在浏览器地址栏输入的http://xxxx一度被认为是互联网最典型的特征。实际上,URL是一个资源定位的符号约定,他包括了对于互联网上任何一个资源特征的描述规范,而不仅仅是代表一个域名或者一个网页。它的比较完整的定义是:协议://用户名:密码@网络地址(可以是域名或者IP或者任何其他字符串):端口/地址路径信息?查询key=查询值&查询key=查询值。我们最常见的如http://www.qq.com/,实际上代表:以http协议访问的,可以匿名使用的,在地址是www.qq.com上,以默认端口(这个数字由协议决定,HTTP协议默认是80端口)获得的,在根目录上的资源。

URL逐渐成为开源软件最喜爱的资源标志,是有原因的,其中最重要的原因之一,就是在现在大部分编程语言中,都带有非常完善的处理URL的库,比如java.net.URL类型。这些库可以非常简单的从一个字符串URL中解析出协议、地址、端口、路径、查询KEY和对应的VALUE。如果不是使用URL,那么你可能需要构建一个非常复杂的结构体,来存放如此繁杂的信息。URL受到欢迎的另外一个原因,是因为他本身是一个字符串。而字符串,对于编程来说是最友好的数据结构之一:几乎所有的语言都有字符串类型,你可以简单的在源代码中输入字符串,你可以简单的打印出URL。更重要的是,字符串这种类型,还可以简单的扩展数据,对比于一些结构体,我们需要关注其成员结构、内容长度,而字符串就没有这个问题;当然你也可以使用诸如JSON、XML这类编码的字符串数据,但是对于“标识”一个资源来说,那些也太复杂了点。

也许URL不是一种最高效的标识方法,它远比类似IP地址类型的数字要占用内存,处理过程也没有子网掩码这么快速,但是它对程序员的友好程度绝对是一流的。我们可以看到很多软件都在使用URL:

1. 用JDBC连接MySQL的时候,我们使用的是:

mysql://127.0.0.1:3306/dbname?user=xxx&password=xxx

2. 我们在windows窗口地址栏可以输入http://... ftp://... File://... mailto://...

3. Hadoop里面你可以使用hdfs://host/…来读取一个文件

4. Rsync://xxxx 可以用来同步服务器

HTTP协议

互联网上使用的最广泛协议,一定是HTTP协议。这个协议不是一种特别“高效”的协议:它是基于文本字符串的,它的header居然是按换行符分隔的,它往往是短连接的同时它还居然是使用TCP的……当我们在设计一个客户端-服务器通信的协议时,我们往往会采用长连接的,用来节省反复建立连接的开销;我们喜欢用TLV形式的编码格式(Type:Length:Value),觉得在TCP流中这样处理是最快的;我们喜欢用位来代替字节,用数字代替字符串,这样能节省流量……但是,HTTP协议有几个最典型的优点,是其他我们没有关注的,那就是:可扩展性、请求应答性。

如果我们的协议内容是文本的,以换行符分隔的,那么,我们就无需维护一个有限数量的header,这样任何的使用者,都可以去扩展任意的header,比如HTTP里面就因为增加了著名的Cookie的header,从而让WEB服务变得可以携带会话信息。就连对于HTTP正文的“数据类型”的header,也是一种叫MIME的分类字符串来标识,比如text/html、image/jpeg,任何人都可以创造新的“类型”。HTTP协议另外一个特征,是保持了非常简单的“请求应答”模型,这个模型可以很简单的在一个阻塞的线程里表现,所以对于使用者来说,太容易学习了,你甚至可以用telnet指令来直接模拟一个HTTP的过程。如果按一般我们设计的高效通信模型,我们往往会在一个连接里面承载多次交互,你可以连续发一堆请求,然后收一堆回应,但是HTTP不是这样,因为如果这样设计,整个处理过程会变得复杂:你必须要记录起所有发出的请求,你还要在请求里面放入一个序列号,再从回应中读取对应的序列号,来对应请求……在HTTP里面,没有序列号,无需记录请求,他每个连接,每个时刻,只有一个会话,就是一个请求对应一个回应。这样的简单设计,让我们在使用它的时候,可以用很简单的编程方法来使用,从而扩大了各种各样的使用者。当使用者扩大之后,各种语言,各种平台,都提供了对HTTP协议进行操作的工具库,就算你找不到这样的工具库,你也可以很简单的利用TCP的socket功能来写一个HTTP协议操作库。

我们似乎一下难以举出很多例子使用HTTP协议,原因是,我们接触到的开源软件,其真正的大数据量通信的通道,都不是用HTTP协议的,因为这里确实有性能上的需求。但是,当我们看到各种使用开源软件组合而成的系统,都是使用HTTP接口的,比如Facebook的开放平台的各种接口。这些越来越多的接口,虽然形式上有RESTful的,有WebService的……所有的这些接口,都是基于HTTP协议的。

JSON编码

我们经历过各种各样的编码格式,从最早的计算机课程中,我们就要学习如何用数字来表达文字(使用ASCII表)。在后来,我们使用过CSV格式,就是那种每行文字表示一个序列,每个逗号分开两个字段。再后来,我们发现我们可以用memcpy来把一个结构体拷贝来拷贝去,这也是一种编码,只不过和编译器、操作系统有关。在某个时候,我们发现XML的宣传铺天盖地,似乎这个世界的编码格式终于要统一了。但是在实际的使用过程中,我们发现XML其实是一个超级复杂的概念,就算不管那个复杂的“合法性检查”规范,我们也要掌握DOM和SAX两种奇怪的处理手段。而且,这个号称“对人类友好”的格式,真正用键盘去敲的时候,需要输入那么多字符,才能表达一个很简单的数据。所以有一部分人,觉得XML是一个骗局,他们完全放弃了对“兼容人类读写和机器处理”的理想,采用TLV或者其他一些完全只针对计算机处理的编码格式。他们会写很多处理的工具,以及工具的工具,最著名的是Google Protocol Buffer这个开源工具。另外一部分人,继续探索一种让人类和机器平衡的格式,我们现在有CSV格式,Markdown格式等等,其中最成功的,就是JSON格式。

有一次,我们发现这个流行很广的格式,不是一个“高效”的技术规格。JSON也是全字符串的,他也是基于标识划分字段的,这比起按长度来划分字段的编码格式来说,处理起来是非常浪费内存和CPU的。不过,人类在使用JSON编写和阅读时比较轻松,它还能简单的以树状格式来展示。在AJAX(JavaScript)流行的时代,JSON作为标配的格式,早已突破了JavaScript的使用领域。说实在的,我很难去列举更多JSON的优点,因为它实在是太简单了,几乎简单到,你如果想用文本来表达一种树状结构,最后都会得出类似JSON的东西,差别只是各种标识符不同而已。

Redis可以存储JSON的结构,Chef用JSON来存放部署数据,Apache CouchDB甚至直接就是用JSON作为数据库存储格式。

脚本

相信大家都接触过SQL,这是一种很特别的语言,他似乎不是一种完整的语言,但是他又能做很多事情。我们也使用过XML,这个格式可以用来描述很多东西,曾几何时,大部分的开源软件的配置文件,都是XML格式的,比如Tomcat,Spring,Hibernate,Log4J…我们也有试用过简单的INI格式作为配置,用过Apache那种看起来有点奇怪的格式配置文件,甚至让人莫名其妙的bind配置、network配置……上面所说的这些东西,有一部分是所谓的配置文件,但是从本质来说,这些都是一种用户使用接口。最开始的时候,我们希望能让用户非常简单的去使用已有的软件,因此我们设计了各种各样的配置文件。当这些配置文件越来越复杂,学习如何配置他们的难度,甚至已经和编程不相上下了,比如Spring的XML配置文件。

另外一个方面,软件业界在降低编程难度的努力上,结出了非常多的成果,其中非常突出的一个,就是脚本语言。和最早的perl语言不同,现在的脚本语言,已经非常成熟了,比如python/ruby/lua,这些脚本语言除了具备高效的解析器以外,一般都还具备即时编译的能力(JIT),这让脚本语言好学不好用的名声渐渐褪去。因此,有很多人就想,我们为什么要发明一个奇怪的配置文件格式,而不直接使用某个流行的脚本语言呢?因此在现在最流行的Web服务器Ngix,就采用了lua脚本作为配置文件。我们再也不用去记忆奇怪的Apache配置文件的写法,我们只需要使用lua语言就好了。使用脚本语言的功能扩展性,远比配置文件要强,用户可以利用编程的能力,更好的使用这个程序。在这个方面,SQL实际上是一个非常优秀的前辈,由于有SQL这种接口,数据库软件的使用变得非常的易学,也能很强大,对比更久之前的FoxPro这种数据库,它提供的语法和功能,远远没有SQL那么丰富。

除了能力的强大外,脚本语言还是一种通用知识,使用者的学习精力不用被浪费在某个特别的软件上。对于使用者来说,也是一种特别的吸引力,毕竟,我花时间学习了lua语言,并不仅仅可以用在配置ngix上,我还可以用来写wow的UI界面插件。

更进一步,我们的开源库、框架,以前往往会假定,使用者和源代码是同一种语言,比如著名的Cocos2d-X游戏引擎。但是,更多的开源库,更喜欢提供脚本形式的接口,比如Unity游戏引擎,就提供了C#和JS两种脚本语言(C#可能算不上脚本语言),这样能让用户在易用性上得到更好的服务。这显然会让这些开源库和框架的复杂度,但是也让这些软件的用户市场得到极大的扩展。现在Cocos2d-Lua已经越来越多人用,就是脚本威力的证明。毕竟我们所有人,都希望能更快的完成工作。

RESTful接口

前文已经说到过HTTP协议,事实上,很多年前,很多人已经在使用HTTP协议作为软件模块、进程间的交互方式。但是,我们发现HTTP仅仅是一个应用层的传输协议,你可以用来做任何事情。因此最先被人想到的,就是用来模拟函数调用,这也是所谓RPC(远程过程调用),于是WebService诞生了,有些公司还进一步,对于内容编码格式也提供了,比如SOAP编码协议。但是这些技术,虽然知名度很高,但真正的使用者却更少。到后来,有一些更加复杂的所谓“企业级”技术诞生,比如EJB,这种技术提供了强大的“非功能性”能力,比如高可用性、高伸缩性、自动扩容容灾,balabala…但是这种技术能提供的“功能”却非常少,对比要把这套东西配置构建起来的复杂努力,对比实在太大了。

因此终于有聪明人发现了RESTful,并且流行起来。使用RESTful,终于能让我们摆脱“不够高大上”的心理压力——因为业界都很流行嘛,但是实际上,大家还是看重它的易用性。我们甚至无需任何特别的库和工具,就用现有的HTTP协议工具,就能使用和构建RESTful服务。并且这个技术还有很好的一点,就是我们再也不用提供各种语言各种平台的SDK接口库了,我们看到各种开放平台和数据系统,都抛弃了旧的SDK接口库模型,而采用了RESTful接口。——如果我们SDK要升级,还会让用户的代码崩溃的话,我们不如直接用这种基于文本和自描述的技术来提供接口。

总体来说,RESTful有它技术上的独特之处,但是让它流行起来的原因,其实还是一个简单的原因——易用性。

Web管理界面

在早期的开源项目中,我们如果要控制一个软件,或者监视这个软件的运行情况,往往都只有非常简陋的手段:配置文件和日志文件。比如Apache这款软件,他的配置文件和日志文件都是非常复杂的,基于acesss_log的这个文件,甚至出现了大量的其他开源软件,用来专门“展示”这个内容超级丰富的日志文件。而另外一些软件,提供了一个命令行界面,我们可以用一些文本命令,去控制这款软件。最著名的例子就是redis,其实MySQL来说也是这种,只不过这个命令是SQL。

不可否认,不管是日志文件,还是命令行,都是非常强大能力。他们的表达能力非常强,能够对非常复杂的功能提供支持。但是他们也有一个最严重的问题,就是“提示力”不足:对于用户来说,他是不知道这个软件有什么信息的,更加没法快速的学会怎么使用。提供给他们的,只有各种手册、文档。但是,有一些软件,提供了一个Web的管理界面,就能让这些复杂的手册、文档统统变得没必要了,因为用户可以直接在这个图形界面上探索。这方面最突出的成功例子,就是discuz。以前我们要安装一个网上论坛,我们需要操作命令行、脚本、SQL……,但是这个软件,从安装、维护、使用,都可以通过WEB的图形界面来使用,猛然的打开了网络论坛的市场。

除了discuz论坛,像tomcat/chef……都是有WEB图形界面的。除了开源软件,我们发现现在的路由器、电视机、投影机甚至都有WEB的操作界面。因为对于用户来说,不管是电脑还是手机,都一定会带有一个浏览器,这样对于软件的操作接口,只需要输入一个URL,就可以发现一个五彩斑斓的界面世界。

总结

上面说的这些,看起来并不是非常高大上的技术,但是这些能流行,最核心的一点,就是易用性。对于开源软件来说,流行是一个最重要的因数,所以易用性是一个非常关键的特性。特别是现在开源软件之间的竞争非常激烈的情况下,易用性已经让用户非常挑剔之后,我们更是要把这些易用性作为一个产品的底线,因为如果不到达这个底线,就会被用户轻易的丢弃。

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。如有不同意见,欢迎后台留言探讨。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 韩大 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • TCP/IP协议
  • URL描述符
  • HTTP协议
  • JSON编码
  • RESTful接口
  • Web管理界面
  • 总结
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档