Micro是一套微服务构建工具库。对于微服务架构的应用,Micro提供平台层面、高度弹性的工具组件,让服务开发者们可以把复杂的分布式系统以简单的方式构建起来,并且尽可能让开发者使用最少的时间完成基础架构的构建。

Go Micro简介

micro工具库由以下几个部分组成:

  • api - API Gateway 网关。它是独立的HTTP入口,基于服务发现机制实现动态路由。
  • web - Web Dashboard web控制台。 提供可视化的发现与管理监控界面。
  • cli - Command line interface 命令行接口。提供描述、查询终端服务的交互入口。
  • bot - Slack与hipchat bot消息通知工具。也就是通过消息传递的CLI。
  • new - 新服务构建模板。

安装相关依赖和插件

  • go 版本

go版本要求 > 1.11

  • GO111MODULE 设置

设置 GO111MODULE 环境变量

export GO111MODULE=on
  • docker

docker安装:docker

  • docker-compose

docker compose安装:docker compose

  • protobuf

protobuf 安装:protobuf

  • consul

consul安装:consul

  • go-micro 及protobuf插件安装

    go get -u -v github.com/micro/go-micro
    go get -u -v github.com/golang/protobuf/{proto,protoc-gen-go}
    go get -u -v github.com/micro/protoc-gen-micro

使用Go Micro编写微服务

service部分

编写rpc.proto

syntax = "proto3";

package rpc;

message BookInfoReq {
    int64 book_id = 1;
}

message BookInfoResp {
    Book book = 1;
}

message Book {
    int64 book_id = 1;
    string book_name = 2;
    string author_name = 3;
    string introduction = 4;
    int64 book_state = 5;
    string book_tags = 6;
    int64 book_need_pay = 7;
    int64 book_published_time = 8;
    int64 book_last_update_time = 9;
    int64 book_category_id = 10;
    int64 book_word_count = 11;
    string cover_url = 12;
    int64 book_view_count = 13;
    int64 book_search_count = 14;
}

编写book.proto

syntax = "proto3";

package book;

//导入model
import "micro_sample/srv/proto/model/rpc.proto";

//定义book service
service Book {
    //书籍信息
    rpc Info (rpc.BookInfoReq) returns (rpc.BookInfoResp) {
    }
}

进入book.protorpc.proto所在目录分别执行以下命令,用于生成go-mirco所需文件和rpc通信所需文件

 protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. *.proto

编写bookhandler.go

package handler

import (
    "context"
    "encoding/json"
    "fmt"
    "micro_sample/srv/proto/model"
)

//实现BookHandler interface
type Book struct {
}

var bookInfo = `{
    "book_id": 82413,
    "book_name": "超级奶爸",
    "author_name": "慕容秋一",
    "introduction": "他,是一个洁身自好的牛郎;\r\n他,是一个坑蒙拐骗的混混;\r\n他,是一个手艺高超的厨师;\r\n他,是一个医术高明的大夫;\r\n他,是一个心狠手辣的杀手;\r\n但,这一切都不是他的正职,老爸,才是他最开心最专注的职业。\r\n无论是谁,只要动了我的宝贝女儿,都会为此付出惨重的代价!!!\r\n然而,当她真的动了他的女儿的时候,他却认真的说:“你连我也一起动了吧!”",
    "book_state": 1,
    "book_tags": "萧何  戴紫涵  杨若兮 萧雨",
    "book_need_pay": 0,
    "book_published_time": 1542650596,
    "book_last_update_time": 1277189030,
    "book_category_id": 11,
    "book_word_count": 266165,
    "cover_url": "https://img.yueduyun.com/book/82/82413.jpg"
}`

func (b *Book) Info(ctx context.Context,req *rpc.BookInfoReq, rsp *rpc.BookInfoResp) error {
    //实际业务处理
    var book = rpc.Book{}
    err := json.Unmarshal([]byte(bookInfo), &book)
    if err != nil {
        fmt.Println("json unmarshal err: ",err)
    }
    rsp.Book = &book
    return nil
}

编写service.go

package main

import (
    "github.com/micro/go-micro"
    "micro_sample/srv/handler"
    "micro_sample/srv/proto/book"
)

func main() {
    // init service
    service := micro.NewService(
        micro.Name("go.micro.srv.novel.v1"),
    )
    service.Init()
    // register handler
    book.RegisterBookHandler(service.Server(), &handler.Book{})
    // run server
    if err := service.Run(); err != nil {
        panic(err)
    }
}

api 部分

编写book.go

package handler

import (
    "context"
    "encoding/json"
    "fmt"
    api "github.com/micro/go-api/proto"
    "micro_sample/srv/proto/book"
    rpc "micro_sample/srv/proto/model"
    "net/http"
    "strconv"
)

type Book struct {
    BookService book.BookService
}

//response data
type RspData struct {
    Code int64       `json:"code"`
    Msg  string      `json:"msg"`
    Data interface{} `json:"data"`
}

//Get method param
func Query(req *api.Request, key string) string {
    pair, ok := req.Get[key]
    if pair == nil || !ok {
        fmt.Println("not found key")
        return ""
    }
    if len(pair.Values) == 0 {
        return ""
    }
    return pair.Values[0]
}

//return json
func ReturnJson(rsp *api.Response, data *RspData) {
    b, err := json.Marshal(data)
    if err != nil {
        fmt.Println(fmt.Sprintf("json.Marshal err = %v", err))
    }
    rsp.Body = string(b)
}

//go-micro serviceName:novel 
//rpc service name:book
//path:http://localhost:8080/go-micro serviceName/rpc service name/rpcmethodName==>http://localhost:8080/novel/book/info
func (b *Book) Info(ctx context.Context, req *api.Request, rsp *api.Response) error {
    bookId := Query(req, "book_id")
    bId, err := strconv.ParseInt(bookId, 10, 64)
    var data = RspData{}
    if err != nil {
        data = RspData{Code: http.StatusBadRequest, Msg: "invalid params", Data: nil}
    } else {
        resp, _ := b.BookService.Info(ctx, &rpc.BookInfoReq{BookId: bId})
        data = RspData{Code: http.StatusOK, Msg: "success", Data: resp}
    }
    ReturnJson(rsp, &data)
    return nil
}

编写api.go

package main

import (
    "github.com/micro/go-micro"
    "log"
    "micro_sample/api/handler"
    "micro_sample/srv/proto/book"
)

func main() {
    //create service
    service := micro.NewService(
        micro.Name("go.micro.api.novel.v1"),
    )
    //init service
    service.Init()
    bookService := book.NewBookService("go.micro.srv.novel.v1", service.Client())
    err := service.Server().Handle(
        service.Server().NewHandler(
            &handler.Book{BookService: bookService},
        ),
    )
    if err = service.Run(); err != nil {
        log.Fatal(err)
    }
}

测试微服务

  • 启动consul

    ➜  ~ consul agent --dev
  • 启动service,并采用consul作为服务发现

    ➜  srv go run service.go --registry=consul
    2019/05/27 00:51:08 Transport [http] Listening on [::]:53780
    2019/05/27 00:51:08 Broker [http] Connected to [::]:53781
    2019/05/27 00:51:08 Registry [consul] Registering node: go.micro.srv.novel.v1-9659fbd6-570c-480e-a38d-d0197f2298f9
  • 启动api,并采用consul作为服务发现

    ➜  api go run api.go --registry=consul    
    2019/05/27 00:51:13 Transport [http] Listening on [::]:53785
    2019/05/27 00:51:13 Broker [http] Connected to [::]:53786
    2019/05/27 00:51:13 Registry [consul] Registering node: go.micro.api.novel.v1-7d03e2d7-5459-4719-88cf-5bdc865c3df6
  • 启动go micro api 并采用consul作为服务发现

    ➜  micro_sample micro --registry=consul api --handler=api
    2019/05/27 00:54:43 Registering RPC Handler at /rpc
    2019/05/27 00:54:43 Registering API Request Handler at /
    2019/05/27 00:54:43 HTTP API Listening on [::]:8080
    2019/05/27 00:54:43 Transport [http] Listening on [::]:53918
    2019/05/27 00:54:43 Broker [http] Connected to [::]:53919
    2019/05/27 00:54:43 Registry [consul] Registering node: go.micro.api-05d5525f-4523-4643-88c7-a44c926ebfb4
  • 访问http://127.0.0.1:8080/novel/v1/book/info?book_id=1

Golang 微服务实践 —— Go Micro

  • 访问http://127.0.0.1:8500 查看服务列表

Golang 微服务实践 —— Go Micro

文章目录