RESTful 是目前最为流行的一种互联网软件结构。因为它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

什么是 REST

REST(REpresentational State Transfer),首次出现在 2000 年 Roy Thomas Fielding 的博士论文中,它指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful 的。

  • 资源(Resources),REST 是“表现层状态转化”,其实它省略了主语。“表现层”其实指的是“资源”的“表现层”。那么什么是资源呢?我们平时网上访问到图片、文字、文档、多媒体等就是资源,一般通过 URI 来定位。也就是说,一个 URI 就表示一个资源。
  • 表现层(Representation),资源是作为一个具体的实体信息,它可以有多种的展现方式。而把实体展现出来就是表现层。例如一个 txt 文本信息,它可以输出成 html、json 等。
  • 状态转化(State Transfer),访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,就涉及到数据和状态的变化。而 HTTP 协议是无状态的,那么这些状态肯定保存在服务器端,所以如果客户端想要通知服务器端改变数据和状态的变化,就要通过某种方式来通知它。客户端能通知服务器端的手段,只能是 HTTP 协议。具体来说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源(也可以用于更新资源),PUT 用来更新资源,DELETE 用来删除资源。

综上所述,我们总结一下什么是 RESTful 架构:

1、每一个 URI 代表一种资源

2、客户端和服务端之间,传递这种资源的某种表现层

3、客户端通过四个 HTTP 动词,对服务端资源进行操作,实现“表现层状态转化”

将它们概述为图片形式,则 REST 架构图为:

REST 的扩展性:

什么是 RPC

RPC(Remote Procedure Call Protocol)远程过程调用协议,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。它假定某些传输协议的存在,如 TCP 或 UDP,以便为通信程序之间携带信息数据。通过它可以使函数调用模式网络化。在 OSI 网络通信模型中,RPC 跨越了传输层和应用层。RPC 使得开发包括网络分布式多程序在内的应用程序更加容易。

工作原理

运行时,一次客户端对服务器的 RPC 调用,其内部操作大致有如下步骤:

1、调用客户端句柄;执行传送参数

2、调用本地系统内核发送网络消息

3、消息传送到服务端

4、服务器句柄得到消息并取得参数

5、执行远程过程

6、执行的过程将结果返回服务器句柄

7、服务器句柄返回结果,调用远程系统内核

8、消息传回本地主机

9、客户端句柄由内核接收消息

10、客户端接收句柄返回的数据

REST vs RPC

在做 API 服务器开发时,很多人都会遇到这个问题 —— 选择 REST 还是 RPC。RPC 相比 REST 的优点主要有 3 点:

1、RPC+Protobuf 采用的是 TCP 做传输协议,REST 直接使用 HTTP 做应用层协议,这种区别导致 REST 在调用性能上会比 RPC+Protobuf 低

2、RPC 不像 REST 那样,每一个操作都要抽象成对资源的增删改查,在实际开发中,有很多操作很难抽象成资源,比如登录操作。所以在实际开发中并不能严格按照 REST 规范来写 API,RPC 就不存在这个问题

3、RPC 屏蔽网络细节、易用,和本地调用类似

但是 REST 相较 RPC 也有很多优势:

1、轻量级,简单易用,维护性和扩展性都比较好

2、REST 相对更规范,更标准,更通用,无论哪种语言都支持 HTTP 协议,可以对接外部很多系统,只要满足 HTTP 调用即可,更适合对外,RPC 会有语言限制,不同语言的 RPC 调用起来很麻烦

3、JSON 格式可读性更强,开发调试都很方便

4、在开发过程中,如果严格按照 REST 规范来写 API,API 看起来更清晰,更容易被大家理解

其实业界普遍采用的做法是,内部系统之间调用用 RPC,对外用 REST,因为内部系统之间可能调用很频繁,需要 RPC 的高性能支撑。对外用 REST 更易理解,更通用些。

一个基本的 Web Server

一个 RESTful 服务本质上首先是一个 Web service。下面是一个最简单的 Web server,对于任何请求都简单的直接返回请求链接:

package main

import (
"fmt"
"html"
"log"
"net/http"
) func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}) log.Fatal(http.ListenAndServe(":8080", nil))
}

编译运行之后,使用 curl 测试,结果如下:

$ curl -v -XGET -H "Content-Type: application/json" http://127.0.0.1:8080/user

Hello, "/user"

路由功能

很显然,我们的线上项目不可能使用这么简单的 API 服务器。当用户增加,请求也会不断上涨,该如何处理好这些请求?作者使用了一个开源路由框架 mux。这是一个小巧高效,且使用较广的第三方框架。接下来的篇幅里,作者会使用 mux 搭建一个 API 服务器框架。

安装 mux

$go get github.com/gorilla/mux

Router

//Router.go
import (
"net/http" "github.com/gorilla/mux"
) type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
} type Routes []Route func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
var handler http.Handler handler = route.HandlerFunc
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w, r)
}) router.Methods(route.Method).Path(route.Pattern).Name(route.Name).Handler(handler)
}
return router
} var routes = Routes{
Route{
"DeleteItem",
"DELETE",
"/v1/delete",
v1_deleteItem,
},
...
}

Handler

//Handler.go
func v1_deleteItem(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusOK, Text: "操作成功"}); err != nil {
log.print("%s\n%s", err.Error(), debug.Stack())
}
}

整体 mux 功能实现:

//main.go
func main() {
router := NewRouter() log.print("service running(PID:%d)...", os.Getpid())
log.Fatal(http.ListenAndServe(":8080", router))
}

API 基本框架已经实现,接下来就是将相应功能实现模块与相应接口对接即可。

写在最后

对于想要学习作为一个客户端开发者如何独立完成一个具有 API 服务器功能的线上 APP,可以参考专栏《如何独立开发一个完整应用》,专栏中使用线上 APP 靓手艺 作为案例,详细分享了笔者如何实现 APP 全部功能。

实现一个 RESTful API 服务器的更多相关文章

  1. 使用python的Flask实现一个RESTful API服务器端

    使用python的Flask实现一个RESTful API服务器端 最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文 ...

  2. 使用python的Flask实现一个RESTful API服务器端[翻译]

    最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文将会使用python的Flask框架轻松实现一个RESTful的服务 ...

  3. 一个Restful Api的访问控制方法

    最近在做的两个项目,都需要使用Restful Api,接口的安全性和访问控制便成为一个问题,看了一下别家的API访问控制办法. 新浪的API访问控制使用的是AccessToken,有两种方式来使用该A ...

  4. 转:使用python的Flask实现一个RESTful API服务器端

    提示:可以学习一下flask框架中对于密码进行校验的部分.封装了太多操作. 最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了 ...

  5. 转:一个Restful Api的访问控制方法(简单版)

    最近在做的两个项目,都需要使用Restful Api,接口的安全性和访问控制便成为一个问题,看了一下别家的API访问控制办法. 新浪的API访问控制使用的是AccessToken,有两种方式来使用该A ...

  6. 使用 SpringBoot 构建一个RESTful API

    目录 背景 创建 SpringBoot 项目/模块 SpringBoot pom.xml api pom.xml 创建 RESTful API 应用 @SpringBootApplication @C ...

  7. 用 Go 快速开发一个 RESTful API 服务

    何时使用单体 RESTful 服务 对于很多初创公司来说,业务的早期我们更应该关注于业务价值的交付,而单体服务具有架构简单,部署简单,开发成本低等优点,可以帮助我们快速实现产品需求.我们在使用单体服务 ...

  8. Java——搭建自己的RESTful API服务器(SpringBoot、Groovy)

    这又是一篇JavaWeb相关的博客,内容涉及: SpringBoot:微框架,提供快速构建服务的功能 SpringMVC:Struts的替代者 MyBatis:数据库操作库 Groovy:能与Java ...

  9. nodejs 搭建 RESTful API 服务器的常用包及其简介

    常用包 框架: yarn add express 数据库链接: yarn add sequelize yarn add mysql2 处理 favicon: yarn add serve-favico ...

随机推荐

  1. Django路由系统---django重点之url命名分组

    django重点之url命名分组[参数无顺序要求]. settigs.py:增加STATICFILES_DIRS静态资源路径配置,名称为创建的文件夹名称 'DIRS': [os.path.join(B ...

  2. phpstrom设置php环境

    phpstorm设置自动同步服务器 Tools->Deployment->Confinguration 点+号,添加服务器,类型SFTP,输入name 点击ok,项目与服务器连接成功! 设 ...

  3. Java日期格式化参数对照表

    Symbol Meaning Presentation Example G era designator Text AD y year Number 2009 M month in year Text ...

  4. 4、Node.js REPL(交互式解释器)

    Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Window 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并 ...

  5. java String 常用方法集合

    String a = "abc";String b = "abc";a==b ;//返回true,因为a,b指向的是同一个地址 String a = new S ...

  6. 原生JS写了一个小demo,根据输入的数字生成不同背景颜色的小方块儿~

    昨天练习写了这个小demo,个人觉得通过设置定位元素left和top的值,来实现换行的功能,这种方法很巧妙~ 另外,如下代码中的随机颜色的获取,还请各位前辈多多指教:需要改进的地方:或者有没有更好的方 ...

  7. BZOJ 1084 最大子矩阵 dp

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1084 题目大意: 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分 ...

  8. BZOJ2761:[JLOI2011]不重复数字(map)

    Description 给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 ...

  9. TensorFlow函数(五)参数初始化方法

    1.初始化为常量 tf.constant_initializer(value, dtype) 生成一个初始值为常量value的tensor对象 value:指定的常量 dtype:数据类型 tf.ze ...

  10. Samba服务器的配置与使用

    1.系统环境变量 Fedora: yum install libacl-devel libblkid-devel gnutls-devel \ readline-devel python-devel ...