go 微服务(1)

作者: zidea | 来源:发表于2020-05-01 20:08 被阅读0次
    golang.png

    今天是5.1劳动节,首先祝大家 5.1 劳动节快乐,疫情多少对大家又会有所影响,影响您的工作,影响您的出行,影响您的新年的计划。可能因为疫情大家也养成一些好的习惯,勤洗手将强锻炼身体提供抵抗力。

    may_day.jpeg

    今天带来的是微服务,微服务是一种概念,也是因今天互联网需求所带来解决当今互联网的问题解决方案,已经不算什么新事物,在一些大公司已经开始实现了微服务架构,其实早在提出这个概念前,阿里就已经有了微服务,我们都是有了实现,然后找一个时髦概念对这些技术加以总结和描述。

    今天选择 go 语言来实现微服务,分享内容会从很基础 Http 服务开始,一步一步实现微服务,分享也是参考老外教程并搜集一些相关资料。

    • 简单服务器搭建
    • 实现 Restful 服务
    • Gorilla 重构 Restful 服务
    • go 语言自带 rpc 包
    • 介绍 gRPC
    • docker 部署

    简单服务器搭建

    使用 go 语言内置 http 包来开发客户端和服务端,go 语言 http 包设计是比较优雅的包。从 http 包可以看出go 语言设计人员深厚功底。写一个简单 web 服务仅用 go 提供 http 包就住够了。这个和其他支持服务器开发语言例如 java 有有所不同。有关 http 协议

    package main
    
    import "net/http"
    
    func main() {
        //创建 web 服务
        http.ListenAndServe(":4600", nil)
    }
    
    

    在 go 语言创建一个服务是比较轻松的一件事,通过上面简简单单的几行代码我们就实现了一个服务。运行 go run main.go 我们就启动了服务,可以使用 curl 命令进行验证。
    ListenAndServe 接收两个参数第一参数是服务器地址,第二参数是接口类型,这里暂时传 nil

    curl -v localhost:4600
    

    使用 curl 的 verbose 模式来对刚刚创建好的服务进行访问。访问会返回 404 ,这是因为我们还没有对请求进行处理的原因。虽然我们写代码很简答,但是 go 语言 http 包背后做了很多事,创建默认服务结构体来处理请求。随后我们会自己实现服务结构体来替换掉 go 默认提供服务结构体。

    路由处理程序

    我们可以定义路由处理程序来处理和响应用户请求,调用 http

    http.HandleFunc("/", func(http.ResponseWriter, *http.Request) {
        log.Println("Hello World")
    })
    

    每一次访问路径 / 都会由函数 http.HandleFunc 来处理请求,这里简单通过log.Println("Hello World")来验证一下是否访问 / 路径时会执行该函数。
    http.HandleFunc 接收两个参数

    • 路由匹配的字符串
    • func(ResponseWriter, *Request)类型的函数

    http 包会将函数进行注册作为默认 ServeMUX 路由管理器的 /路径上。那么什么是serveMUX,本质上 ServeMux 只是一个路由管理器。本身也实现了 Handler 接口的 ServeHTTP 方法。我们可自己定义实现 ServeHTTP 的 ServeMUX,随后在代码中将演示如何做这件事。

    HandleFuncDefaultServeMux中注册匹配/路由的 handler函数,接下来注册一个处理/goodbye路由的处理程序如下

    http.HandleFunc("/goodbye", func(http.ResponseWriter, *http.Request) {
        log.Println("good bye")
    })
    

    其中服务后,在终端输入来检查上面代码是否 work。

    curl -v localhost:4600/goodbye
    
    • ResponseWriter
    • Request
    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        log.Println("Hello World")
        d, _ := ioutil.ReadAll(r.Body)
        log.Printf("Data %s\n", d)
    })
    

    通过ioutil.ReadAll读取请求体输入,输出到控制台。

    curl -v -d 'Zidea' localhost:4600/
    
    • -d 执行请求在请求体中加入数据

    输出结果为

    Data Zidea
    

    客户端输出

    可以调用fmt.Fprintf将字符串在客户端进行输出

    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
            log.Println("Hello World")
            d, _ := ioutil.ReadAll(r.Body)
            // log.Printf("Data %s\n", d)
            fmt.Fprintf(rw, "Hello %s\n", d)
        })
    

    异常处理

    在 go 语言没有 trycatch 机制,将所有错误一个值形式返回,通过判断 err 是否存在来进行错误处理,这一点对于 nodejs 开发经验应该不会陌生,不过有些人认为这种错误处理机制并不优雅。不过我们暂时接受这种错误处理形式,并且养成一个处理错误好习惯。所以我们现在对于读取请求错误进行处理,读取请求头失败在返回头给出错误信息,有关http请求状态希望大家阅读相关资料进行掌握。

    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        d, err := ioutil.ReadAll(r.Body)
        if err != nil{
            rw.WriteHeader(http.StatusBadRequest)
            rw.Write([]byte("Ooops"))
            return
        }
        fmt.Fprintf(rw, "Hello %s\n", d)
    })
    
    

    不过 http 包中已经提供封装好的方法供我们调用,http.Error,第一个参数为ResponseWriter,第二个参数为返回信息,第三个参数为错误状态码。

        http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
            d, err := ioutil.ReadAll(r.Body)
            if err != nil {
                http.Error(rw, "Oops", http.StatusBadRequest)
                return
            }
            fmt.Fprintf(rw, "Hello %s\n", d)
        })
    

    重构代码结构

    • 在项目下创建 handlers 文件用于放置 handler 文件
    • 创建 hello 文件,因为 hanlders 文件夹下所以无需在文件名后面添加后缀 Handler 表示功能为 Handler。
    • 定义结构体 Hello

    实现了 ServeHTTP 方法我们就实现 Handler 的接口,

    func (h *Hello) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
        d, err := ioutil.ReadAll(r.Body)
        if err != nil {
            http.Error(rw, "Oops", http.StatusBadRequest)
            return
        }
        fmt.Fprintf(rw, "Hello %s\n", d)
    }
    
    

    相关文章

      网友评论

        本文标题:go 微服务(1)

        本文链接:https://www.haomeiwen.com/subject/metcghtx.html