實現一個 RESTful API 服務器

RESTful 是目前最爲流行的一種互聯網軟件結構。由於它結構清晰、符合標準、易於理解、擴展方便,因此正獲得愈來愈多網站的採用。html

什麼是 REST

REST(REpresentational State Transfer),首次出如今 2000 年 Roy Thomas Fielding 的博士論文中,它指的是一組架構約束條件和原則。知足這些約束條件和原則的應用程序或設計就是 RESTful 的。git

  • 資源(Resources),REST 是「表現層狀態轉化」,其實它省略了主語。「表現層」其實指的是「資源」的「表現層」。那麼什麼是資源呢?咱們平時網上訪問到圖片、文字、文檔、多媒體等就是資源,通常經過 URI 來定位。也就是說,一個 URI 就表示一個資源。
  • 表現層(Representation),資源是做爲一個具體的實體信息,它能夠有多種的展示方式。而把實體展示出來就是表現層。例如一個 txt 文本信息,它能夠輸出成 html、json 等。
  • 狀態轉化(State Transfer),訪問一個網站,就表明了客戶端和服務器的一個互動過程。在這個過程當中,就涉及到數據和狀態的變化。而 HTTP 協議是無狀態的,那麼這些狀態確定保存在服務器端,因此若是客戶端想要通知服務器端改變數據和狀態的變化,就要經過某種方式來通知它。客戶端能通知服務器端的手段,只能是 HTTP 協議。具體來講,就是 HTTP 協議裏面,四個表示操做方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操做:GET 用來獲取資源,POST 用來新建資源(也能夠用於更新資源),PUT 用來更新資源,DELETE 用來刪除資源。

綜上所述,咱們總結一下什麼是 RESTful 架構:github

一、每個 URI 表明一種資源web

二、客戶端和服務端之間,傳遞這種資源的某種表現層json

三、客戶端經過四個 HTTP 動詞,對服務端資源進行操做,實現「表現層狀態轉化」bash

將它們概述爲圖片形式,則 REST 架構圖爲:服務器

REST架構圖

REST 的擴展性:網絡

REST 的擴展性

什麼是 RPC

RPC(Remote Procedure Call Protocol)遠程過程調用協議,是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。它假定某些傳輸協議的存在,如 TCP 或 UDP,以便爲通訊程序之間攜帶信息數據。經過它可使函數調用模式網絡化。在 OSI 網絡通訊模型中,RPC 跨越了傳輸層和應用層。RPC 使得開發包括網絡分佈式多程序在內的應用程序更加容易。架構

工做原理

RPC工做流程圖

運行時,一次客戶端對服務器的 RPC 調用,其內部操做大體有以下步驟:app

一、調用客戶端句柄;執行傳送參數

二、調用本地系統內核發送網絡消息

三、消息傳送到服務端

四、服務器句柄獲得消息並取得參數

五、執行遠程過程

六、執行的過程將結果返回服務器句柄

七、服務器句柄返回結果,調用遠程系統內核

八、消息傳回本地主機

九、客戶端句柄由內核接收消息

十、客戶端接收句柄返回的數據

REST vs RPC

在作 API 服務器開發時,不少人都會遇到這個問題 —— 選擇 REST 仍是 RPC。RPC 相比 REST 的優勢主要有 3 點:

一、RPC+Protobuf 採用的是 TCP 作傳輸協議,REST 直接使用 HTTP 作應用層協議,這種區別致使 REST 在調用性能上會比 RPC+Protobuf 低

二、RPC 不像 REST 那樣,每個操做都要抽象成對資源的增刪改查,在實際開發中,有不少操做很難抽象成資源,好比登陸操做。因此在實際開發中並不能嚴格按照 REST 規範來寫 API,RPC 就不存在這個問題

三、RPC 屏蔽網絡細節、易用,和本地調用相似

可是 REST 相較 RPC 也有不少優點:

一、輕量級,簡單易用,維護性和擴展性都比較好

二、REST 相對更規範,更標準,更通用,不管哪一種語言都支持 HTTP 協議,能夠對接外部不少系統,只要知足 HTTP 調用便可,更適合對外,RPC 會有語言限制,不一樣語言的 RPC 調用起來很麻煩

三、JSON 格式可讀性更強,開發調試都很方便

四、在開發過程當中,若是嚴格按照 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 所有功能。

相關文章
相關標籤/搜索