微服务系列笔记之Mico Api详解

导语

上一篇文章中有了入门案例,现在是不是有了很好的理解,不过有个前提是你需要了解grpc技术,简单的来说grpc是一个通信框架,micro是类似的一个通信框架,只不过这个框架应用于微服务中。因此如果你还未了解grpc技术,仍然建议你学习grpc基础,便于更好的理解本篇文章。

准备工作

## 安装go-micro
go get github.com/micro/go-micro
## 安装micro
go get github.com/micro/micro
## 安装grpc
go get -u google.golang.org/grpc
## 安装grpc插件
go get -u github.com/golang/protobuf/protoc-gen-go
## 安装micro插件
go get github.com/micro/protoc-gen-micro
# 设置环境变量,便于命令行操作
export PATH=$PATH:$GOPATH/bin

Micro API

如果你做过web开发,Http请求是无法避免的,服务端需要接受请求并返回相应的结果,但是这种情况下,如何才能在Go Micro中实现呢?其实在Micro中官方为我们提供了API网关micro api。对API的请求将有HTTP提供,并通过服务发现我们的路由。简单来说使用API​​网关模式为你的服务提供单个公共入口点。micro api服务于HTTP并使用服务发现动态路由。由于micro api基于go-micro开发,因此它同时具备了服务发现,负载均衡等能力。是可插拔的一个微服务。

如何使用

启动

micro api [command options] [arguments...]

options选项

--address:用来设置api地址,例如:0.0.0.0:8080
--handler:用来指定用于将HTTP请求映射到服务的请求处理程序,值有四个:api,event,http,rpc。
--namespace:设置api的命名空间,例如:go.micro.api,使用这个之后,http请求之后,才会解析api所在的路由
--resolver:设置api使用的主机名解析程序,值有三个:host,path,grpc。

小试牛刀

服务端

定义api.proto,这里需要注意的是我们定义了两个服务分别是Example 和 Foo,下面模拟Http请求结构体,其实Go-micro直接为我们封装了这部分如图


image

这里我们只是贴上源码,方便大家理解。

syntax = "proto3";

package go.micro.api.example;

service Example {
    rpc Call(Request) returns(Response);
}

service Foo {
    rpc Bar(Request) returns(Response);
}


message Pair {
    string key = 1;
    repeated string values = 2;
}
// 一个Http请求
message Request {
    string method = 1;
    string path = 2;
    map<string, Pair> header = 3;
    map<string, Pair> get = 4;
    map<string, Pair> post = 5;
    string body = 6;
    string url = 7;
}
// 一个Http响应
message Response {
    int32 statusCode = 1;
    map<string, Pair> header = 2;
    string body = 3;
}
// 一个Http事件
message Event {
    // e.g login
    string name = 1;
    // uuid
    string id = 2;
    // unix timestamp of event
    int64 timestamp = 3;
    // event headers
    map<string, Pair> header = 4;
    // the event data
    string data = 5;
}

编写我们的服务端代码

type Example struct{}

type Foo struct{}

// Example.Call 通过API向外暴露为/example/call,接收http请求
func (e *Example) Call(ctx context.Context, req *api.Request, rsp *api.Response) error {
    log.Log("Example.Call接口收到请求")
        //获取参数 map[string]*api.Pair数据类型
    name, ok := req.Get["name"]
        // 判断 values数组是否存在值
    if !ok || len(name.Values) == 0 {
        return errors.BadRequest("go.micro.api.example", "参数不正确")
    }

    // 打印请求头
    for k, v := range req.Header {
        log.Log("请求头信息,", k, " : ", v)
    }

    rsp.StatusCode = 200

    b, _ := json.Marshal(map[string]string{
        "message": "我们已经收到你的请求," + strings.Join(name.Values, " "),
    })

    // 设置返回值
    rsp.Body = string(b)

    return nil
}
//
func (f *Foo) Bar(ctx context.Context, req *api.Request, rsp *api.Response) error {
    log.Logf("Foo.Bar接口收到请求")
        //判断请求方法是否是POST
    if req.Method != "POST" {
        return errors.BadRequest("go.micro.api.example", "require post")
    }
        //获得请求头
    ct, ok := req.Header["Content-Type"]
    if !ok || len(ct.Values) == 0 {
        return errors.BadRequest("go.micro.api.example", "need content-type")
    }

    fmt.Println(ct.Values[0])
    if ct.Values[0] != "application/json" {
        return errors.BadRequest("go.micro.api.example", "expect application/json")
    }

    var body map[string]interface{}
    json.Unmarshal([]byte(req.Body), &body)

    // 设置返回值
    rsp.Body = "收到消息:" + string([]byte(req.Body))

    return nil
}

注册我们的服务,这里和之前方法类似,不再强调。

service := micro.NewService(
        micro.Name("go.micro.api.example"),
        micro.Version("latest"),
    )

    service.Init()
    // 注册 example handler
    api.RegisterExampleHandler(service.Server(), new(Example))

    // 注册 foo handler
    api.RegisterFooHandler(service.Server(), new(Foo))

    if err := service.Run(); err != nil {
        log.Fatal(err)
    }

测试

首先启动我们的api

micro api --handler=api --namespace=go.micro.api

image

启动我们的服务端

go run api.go

image

我们这里用postman进行测试如下
测试bar


image

image

测试example


image

查看我们的控制台,同样产生了信息
image

image

结语

掌握本篇知识,总体来说不是很难,阅读时,请耐心思考,自己多加实践,才能更好的掌握。

本篇文章参考Go-Mico官方博客和系列案例
进行总结分享。

推荐阅读


本文欢迎转载,转载请联系作者,谢谢!


打开微信扫一扫,关注微信公众号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343