微服务架构和实践

go 微服务(1)

2020-05-01  本文已影响0人  zidea
golang.png

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

may_day.jpeg

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

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

简单服务器搭建

使用 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 接收两个参数

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
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/

输出结果为

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)
    })

重构代码结构

实现了 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)
}

上一篇下一篇

猜你喜欢

热点阅读