您的位置 首页 golang

golang 微服务(1)

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

今天选择 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,随后在代码中将演示如何做这件事。

HandleFunc DefaultServeMux 中注册匹配 / 路由的 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)
}
  

文章来源:智云一二三科技

文章标题:golang 微服务(1)

文章地址:https://www.zhihuclub.com/86660.shtml

关于作者: 智云科技

热门文章

网站地图