go 构建微服务程序

本文介绍了使用Go语言构建微服务程序,重点探讨了RESTful API的设计与HTTP Resource API的概念,强调了Go语言在微服务开发中的优势。文章涵盖微服务与RESTful的关联,API设计原则,以及Go语言实现REST客户端和服务端开发的基础知识,同时推荐了API Blueprint工具进行API设计、验证和文档自动化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

go 构建微服务程序

Go 是面向现代云服务架构的语言,服务之间通讯在HTTP应用层仅友好支持 RESTful 的服务 。因此,掌握 HTTP Resource API 的设计方法与工具、golang 客户端与服务器编程要点是必须 get 的技能。 本文介绍 API Blueprint 的使用,以及 golang 相关编程,以 API 为核心,支持测试驱动的编程(TDD)

需要支持 soap 服务或 oracle DB2 等数据库,请使用 java 等。

一、微服务 与 RESTful

1.1 微服务的概念

容器使得进程(应用)一次构建到处运行。人们开始思考一个系统一个进程这种开发、运营模式在云时代的合理性。在已有 SOA(Service-oriented architecture) 架构的基础上,提出了“微服务架构”的概念。

Martin Fowler 在2014年用博客明确了微服务的概念,Microservices - a definition of this new architectural term中文翻译

简单来说,微服务架构风格[1]是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。

  • 一个应用由一组服务构成
  • 服务运行在自己的进程
  • 服务间采用 HTTP Resource API

用现在的技术表达,即是一个应用由若干(容器)服务,通过进程间通讯(IPC)组成一个应用。

1.2 HTTP Resource API

1、分布式计算与 IPC 进化历史

intro

  1. 进程间通过 Socket API 通讯
  2. 有了RPC(Remote procedure call)的概念,用 IDL (Interface Description Language) 规范进程间通讯
  3. 面向对象技术的出现:
    • Common Object Request Broker Architecture (CORBA, 1991)
    • remote method invocation (RMI)
    • DCOM
    • EJB
  4. web 技术的出现:
    • Ajax(Asynchronous JavaScript And XML)。 (IE5 with XMLHttpRequest Object 1999)
    • SOAP (Simple Object Access Protocol)。XML-based protocol for web service
    • XML-RPC is an RPC protocol that uses XML to encode its calls and HTTP as a transport mechanism.

基于 SOAP / XML-RPC 构建的 Web Service 协议家族:

ws*

2、RESTful 协议

2000 年 Roy Thomas Fielding 的博士提出面向分布式多媒体软件的 REST (Representational State Transfer) 风格架构,RESTful 服务迅速成为互联网服务的事实标准。

SOAP RPC pk. REST RPC

HTTP message with SOAP for searching on google

GET search/beta2 HTTP/1.1
Host:api.google.com
Content-Type:application/soap+xml
SOAPAction: urn:GoogleSearchAction

<?xml version="1.0" encoding="UTF-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmllsoap.org/soap/envelope/">
    <soup:Body>
        <gs:doGoogleSearch xmlns:gs="urn:GoogleSearch">
            <q>REST</q></gs:doGoogleSearch>
    </soup:Body>
</soap:Envelope>

HTTP message with REST for searching on google

GET services/rest?api_key=xxx&q=REST HTTP/1.1 
Host:api.google.com

程序员的选择?

2.3、HTTP Resource API

HTTP Resource = URL?

HTTP Resource API,使用 GET、POST、PUT、DELETE 等现有 HTTP 指令存取远端资源的 API, 原则上使用 JSON 传输对象

阅读: Gregor Roth REST, 面向资源架构(2009)
原文: RESTful HTTP in practice

要点:

  • 资源(Resource)的概念、识别与组织
    • 个体资源
    • 集合资源
    • 子资源
  • 操作(Action)/ 常用状态码
    • GET, 获取资源
    • PUT,创建或更新
    • DELETE,删除资源
    • POST,创建子资源
    • PATCH,更新部分资源
  • 查询与过滤
    • 查询变量
  • 常用 header 信息
    • Content-Type: application/x-www-form-urlencoded; charset=utf-8
      • text/plan
      • application/x-www-form-urlencoded
      • application/json
      • application/xml
    • Accept: application/json
      • 仅用与 Request header, 与服务器协商如何输出资源
    • Content-Length: 19
      • 等于 0 ,不一定没有 body
  • PUT 与 POST 的区别

跟多关于 RESTful 知识, RESTful Web Services Tutorial

二、API 设计

API 案例: http://lbs.amap.com/api/webservice/guide/api/georegeo

这样的设计好不好? - 请不要妄议,历史因素是每个企业必须面对的问题。

如何表达这样的设计,并知道软件生产与测试是本节要求掌握的知识。

2.1 资源(领域)建模

agenda-resources

建模元素:

  • 实体: 用方框表示,第一栏表示实体的名称,例如 User;第二栏表示属性,语法:属性名:类型=默认值{描述属性} 例如 id:string {key,auto-inc}
  • 关系: 实体之间的约束或需要持久化的状态。关系名称用过去时或状态表达
  • 多重性:一对一,一对多,多对多
  • 导航: 需要从一个实体导出相关实体,用箭头表示

2.2 API 设计

简单的应用我们可以参考前面的文章设计

更简单,可参考 [RESTful API 设计指南]
(http://www.ruanyifeng.com/blog/2014/05/restful_api.html)

[GET]    v1/users - 获取所有用户
[POST]   v1/users - 新建用户
[GET]    v1/users/{id} - 查询用户明细信息
[PATCH]  v1/users/{id} - 修改用户明细信息
[DELETE] v1/users/{id} - 删除用户
[GET]    v1/users/{id}/owned-meetings -  获取用户创建的会议
[GET]    v1/users/{id}/joined-meetings -  获取用户参与的会议
[GET]    v1/meeting
...

单数与复数

上述 API 仅考虑了资源的 CRUD,并没有考虑资源的业务处理。 思考一个,如果我们要验证一个用户或者激活一个用户,它的 Api 应该是什么模样呢?

[GET] v1/user/login{?name,password}
[GET] v1/user/active{?activecode}

[GET] v1/users/login{?name,password}

如果选用复数,则 login 与 用户的 id 将难以区分。使用 单数名词/业务动作{?参数列表} 的设计模式,更加易于理解和处理。

2.3 API 设计工具与文档化

API design First 是微服务架构首先遵循的理念!

上述设计文档不能随着系统同步进化,因此,我们需要一体化工具支持 API 的设计、验证、代码生成(客户端、服务器端)、文档自动化、以及测试自动化。

1、Api Blueprint?

什么是 API Blueprint?

一句话:用 markdown 写 API

*扩展阅读:API 设计: RAML、Swagger、Blueprint三者的比较

竞争产品: apizza

基于云原生应用开发的创新

云服务技术作为新生事物,出现了无数创新型企业,这些企业的丰富并完善了云应用开发的生态环境。中国企业依托国内软件生产的需求,在模仿中获得了成长。以下列表只是一些罗列,对应的国内应用请自己收集:

2、Api Blueprint 快速入门

  1. 用 github Open API 登陆 https://apiary.io/
  2. 创建一个在线项目 agenda
  3. 将 agenda 关联到你的代码仓库
  4. 在线输入以下代码, push 到仓库
FORMAT: 1A
HOST: http://agenda12.apiblueprint.org/

# Agenda

Agenda is a simple API allowing consumers to schedule meeting on-line

# Group User

Resource operations related to a user in the API.

## User-Key [/v1/user/getkey{?username,password}]

+ Parameters
    - username : `root` (string, required) - User Name
    - password : `pass` (required)

### Get User Key [GET]

get a security key for operations later

+ Response 200 (application/json)

        {
            "key":"1e3576bt"
            "permissions":["user","admin"]
        }


# Group Users

Resources related to a users in the API.

## Users Collection [/v1/users{?key}]

+ Parameters
    - key : `1e3576bt` (string, required)

### List all Users [GET]

+ Response 200 (application/json)

        [
            {
                "id":1
                "username":"zhang3"
                "password":"zhang"
                "email":"zhang3@mail2.sysu.edu.cn"
            },{
                "id":2
                "username":"li4"
                "password":"li"
                "email":"li4@mail2.sysu.edu.cn"
            }
        ]

### Create a New User [POST]

+ Request (application/json)

        {
            "username":"zhang3"
            "password":"zhang"
            "email":"zhang3@mail2.sysu.edu.cn"
        }

+ Response 201 (application/json)

    + Headers

            Location: /users/1

    + Body

            {
                "id": 1
                "username":"zhang3"
                "password":"zhang"
                "email":"zhang3@mail2.sysu.edu.cn"
            }

### Get User by ID [GET /v1/users/{id}]

+ Parameters
    - id : `1` (int, required) - User Name

+ Response 200 (application/json)

        {
            "id" : 1
            "username":"zhang3"
            "password":"zhang"
            "email":"zhang3@mail2.sysu.edu.cn"
        }

# Group Meetings

本文档 URL: https://agenda12.docs.apiary.io/#

  • 在 documentation 选择 Get User Key, 选择 Mocker server, 发现网站以为你部署完成了 Mocker 测试网站。 在浏览器输入:
https://private-c2bed8-agenda12.apiary-mock.com/v1/user/getkey?username=root&password=pass

你会得到正确的响应。这是一个 令人激动 的功能,我们已经可以通过该 API ,客户端和服务器并行开发开始了!

3、API Blueprint 文档说明书

进入 https://apiblueprint.org/

  • 系统建议你设计 API 先定义数据,以便于描述接口

进入 tutorial 页面:

  • 先阅读简单介绍
  • Language Specification 是完成接口定义,必须自学的!
  • Examples 官方所用案例,你需要模仿它完成你的 API 设计!

三、Go REST客户端开发

Go REST 客户端主要涉及三个库 net/http ,io/ioutilencode/json

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    res, err := http.Get("http://private-c2bed8-agenda12.apiary-mock.com/v1/user/getkey?username=root&password=pass")
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err)
    }

    retJSON := struct {
        MyKey       string `json:"key"`
        Permissions []string
    }{"w", []string{"w", "w"}}

    w, err := json.Marshal(retJSON)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(w), retJSON)

    fmt.Println(string(body))

    if err := json.Unmarshal(body, &retJSON); err != nil {
        panic(err)
    }

    fmt.Println(retJSON)

}

案例给出用 go http 客户端访问 mock 服务的小程序。

要点

  • http 库提供了常用的三个函数
    • Get
    • Post
    • PostForm
  • defer res.Body.Close()
    • 每个请求都必须关闭 Body 流
  • json 读写
    • struct 属性名称必须是可导出(大写)
    • struct 有三个 json 序列化和反序列化的 tag
      • json:"-" // 禁止转换属性
      • json:"myName" //属性名称映射
      • json:",omitempty" //空值处理,逗号!
      • json:"myName,omitempty" //

RESTful 有更多动作、需要特殊的头、或需要处理重定向?

四、go REST 服务端开发

似乎 REST 服务端开发, urfave/negroni,gorilla/mux,unrolled.render 的组合几乎能完全满足 REST 的任何开发需求。

你必须考虑 RESTful 服务的用户:

  1. 在网页中嵌入 URL 来显示一个 html 组件。如在自己的网站上,使用地图 API 做一个标签
  2. 使用 jQuery, NodeJS 框架的浏览器客户端
  3. 非浏览器客户端

1、友好传统网站

  • 仅使用 GET、POST
  • 使用 application/x-www-form-urlencoded 类型输入,使用 application/json 输出

2、使用 nodejs 框架

  • 服务端输入要处理:
    • 可以使用任意的 GET,POST,PUT,DELETE,PATCH,HEAD …
    • 检测 Content-Type 的文档类型 和 字符编码 以正确处理输入
  • 服务端输出要处理:
    • 检测请求的 Accept 的文档类型,并正确输出对应的文档
    • 要处理 HEADERs 以保证客户端处理 Respose
    • 要正确处理 status, 不仅是 200,404
      • 例如: 201 `创建正确,且在 HEAD 中 LINK 的导航
    • 最烦人的就是 jsonp 格式的输出

浏览器跨域请求

  • 对于现代浏览器
  • 对于传统浏览器必须支持 jsonp

    • 要检测 url 中 callback 参数
    • 检测请求的 Accept 的文档类型 application/jsonp 或 text/script
    • 必须使用 reader.Jsonp 输出
  • 什么是 jsonp ?

    • 浏览器沙箱中只支持相同网站及子网站的请求
    • 但有 src 属性的 tag 例外
    • XMLHTTPRequest 对象,会接受 callbackName("json string") 的 Responce.Body 通过 eval(jsonp) 得到对应的对象

3、非浏览器客户端访问

  • 按 RESTful 规范即可!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值