实现一个 RESTful API 服务器
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 服务器的更多相关文章
- 使用python的Flask实现一个RESTful API服务器端
使用python的Flask实现一个RESTful API服务器端 最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文 ...
- 使用python的Flask实现一个RESTful API服务器端[翻译]
最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文将会使用python的Flask框架轻松实现一个RESTful的服务 ...
- 一个Restful Api的访问控制方法
最近在做的两个项目,都需要使用Restful Api,接口的安全性和访问控制便成为一个问题,看了一下别家的API访问控制办法. 新浪的API访问控制使用的是AccessToken,有两种方式来使用该A ...
- 转:使用python的Flask实现一个RESTful API服务器端
提示:可以学习一下flask框架中对于密码进行校验的部分.封装了太多操作. 最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了 ...
- 转:一个Restful Api的访问控制方法(简单版)
最近在做的两个项目,都需要使用Restful Api,接口的安全性和访问控制便成为一个问题,看了一下别家的API访问控制办法. 新浪的API访问控制使用的是AccessToken,有两种方式来使用该A ...
- 使用 SpringBoot 构建一个RESTful API
目录 背景 创建 SpringBoot 项目/模块 SpringBoot pom.xml api pom.xml 创建 RESTful API 应用 @SpringBootApplication @C ...
- 用 Go 快速开发一个 RESTful API 服务
何时使用单体 RESTful 服务 对于很多初创公司来说,业务的早期我们更应该关注于业务价值的交付,而单体服务具有架构简单,部署简单,开发成本低等优点,可以帮助我们快速实现产品需求.我们在使用单体服务 ...
- Java——搭建自己的RESTful API服务器(SpringBoot、Groovy)
这又是一篇JavaWeb相关的博客,内容涉及: SpringBoot:微框架,提供快速构建服务的功能 SpringMVC:Struts的替代者 MyBatis:数据库操作库 Groovy:能与Java ...
- nodejs 搭建 RESTful API 服务器的常用包及其简介
常用包 框架: yarn add express 数据库链接: yarn add sequelize yarn add mysql2 处理 favicon: yarn add serve-favico ...
随机推荐
- ppt基本操作
一.概述及作用 ppt是一种表达用户思想的有力工具,无论是介绍一个计划,介绍一个新的产品,或是员工报告,员工培训,只要事先做一个演示文稿,那么阐述的过程就会变得见面,简明和清晰. 二.界面构成 演示文 ...
- Nginx学习---企业级nginx环境搭建
1.1. nginx安装环境 1.系统要求 nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境. 1-1 安装 GCC 源码安装nginx需要依赖gcc环境,需要 ...
- magento2常见的命令
常见的命令如下: php bin/magento list 查看所有命令列表 ----------------------------moudule相关的参数------------------ ...
- 用windows公文包实现不同盘符两个文件文件夹文件同步
需求:磁盘D的文件夹A需同步到磁盘E 步骤: 1.在磁盘E中新建公文包B 2.将D盘的文件夹A复制到公文包B 3.修改文件夹A中的内容 4.选中公文包B,右键"全部更新"
- Linux中脚本的使用方法
Linux中脚本的使用方法 一.前言 关于Linux中的脚本的用法,一直没有时间去好好地总结,正好今天下雨,就好好的整理一下思路吧,其实精通了一门语言,比如C语言,学习其他语言需要的成本是非常少的,同 ...
- Entity Framework:代码优先
一.代码优先Code First EF6支持Oracle ODT 12C Release 3 (net4.5) DataModel(类)-->生成数据库DB 或 存在的数据库DB-->生成 ...
- 【转】ios 抓取 tcp/udp 包
原文: http://useyourloaf.com/blog/2012/02/07/remote-packet-capture-for-ios-devices.html Remote Packet ...
- Python常用库之二:Pandas
Pandas是用于数据操纵和分析,建立在Numpy之上的.Pandas为Python带来了两种新的数据结构:Pandas Series和Pandas DataFrame,借助这两种数据结构,我们能够轻 ...
- vector详讲(二)迭代器
先看一下代码: #include <iostream> #include <vector> int main() { std::vector<double> dou ...
- Linux系统的环境变量$PATH
$PATH:决定了shell将到哪些目录中寻找命令或程序,PATH的值是一系列目录,当您运行一个程序时,Linux在这些目录下进行搜寻编译链接. 修改$PATH的方法有很多,比如: export PA ...