转载

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

不忘初心,砥砺前行  

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

作者 | 莫无崖

转载请联系授权 

. 导语

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

. 准备工作

 1## 安装go-micro
 2go get github.com/micro/go-micro
 3## 安装micro
 4go get github.com/micro/micro
 5## 安装grpc
 6go get -u google.golang.org/grpc
 7## 安装grpc插件
 8go get -u github.com/golang/protobuf/protoc-gen-go
 9## 安装micro插件
10go get github.com/micro/protoc-gen-micro
11# 设置环境变量,便于命令行操作
12export PATH=$PATH:$GOPATH/bin

. Micro API

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

. 如何使用

启动

1micro 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直接为我们封装了这部分如图

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

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

 1syntax = "proto3";
 2
 3package go.micro.api.example;
 4
 5service Example {
 6    rpc Call(Request) returns(Response);
 7}
 8
 9service Foo {
10    rpc Bar(Request) returns(Response);
11}
12
13
14message Pair {
15    string key = 1;
16    repeated string values = 2;
17}
18// 一个Http请求
19message Request {
20    string method = 1;
21    string path = 2;
22    map<string, Pair> header = 3;
23    map<string, Pair> get = 4;
24    map<string, Pair> post = 5;
25    string body = 6;
26    string url = 7;
27}
28// 一个Http响应
29message Response {
30    int32 statusCode = 1;
31    map<string, Pair> header = 2;
32    string body = 3;
33}
34// 一个Http事件
35message Event {
36    // e.g login
37    string name = 1;
38    // uuid
39    string id = 2;
40    // unix timestamp of event
41    int64 timestamp = 3;
42    // event headers
43    map<string, Pair> header = 4;
44    // the event data
45    string data = 5;
46}

编写我们的服务端代码

 1type Example struct{}
 2
 3type Foo struct{}
 4
 5// Example.Call 通过API向外暴露为/example/call,接收http请求
 6func (e *Example) Call(ctx context.Context, req *api.Request, rsp *api.Response) error {
 7    log.Log("Example.Call接口收到请求")
 8        //获取参数 map[string]*api.Pair数据类型
 9    name, ok := req.Get["name"]
10        // 判断 values数组是否存在值
11    if !ok || len(name.Values) == 0 {
12        return errors.BadRequest("go.micro.api.example", "参数不正确")
13    }
14
15    // 打印请求头
16    for k, v := range req.Header {
17        log.Log("请求头信息,", k, " : ", v)
18    }
19
20    rsp.StatusCode = 200
21
22    b, _ := json.Marshal(map[string]string{
23        "message": "我们已经收到你的请求," + strings.Join(name.Values, " "),
24    })
25
26    // 设置返回值
27    rsp.Body = string(b)
28
29    return nil
30}
31//
32func (f *Foo) Bar(ctx context.Context, req *api.Request, rsp *api.Response) error {
33    log.Logf("Foo.Bar接口收到请求")
34        //判断请求方法是否是POST
35    if req.Method != "POST" {
36        return errors.BadRequest("go.micro.api.example", "require post")
37    }
38        //获得请求头
39    ct, ok := req.Header["Content-Type"]
40    if !ok || len(ct.Values) == 0 {
41        return errors.BadRequest("go.micro.api.example", "need content-type")
42    }
43
44    fmt.Println(ct.Values[0])
45    if ct.Values[0] != "application/json" {
46        return errors.BadRequest("go.micro.api.example", "expect application/json")
47    }
48
49    var body map[string]interface{}
50    json.Unmarshal([]byte(req.Body), &body)
51
52    // 设置返回值
53    rsp.Body = "收到消息:" + string([]byte(req.Body))
54
55    return nil
56}

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

 1service := micro.NewService(
 2        micro.Name("go.micro.api.example"),
 3        micro.Version("latest"),
 4    )
 5
 6    service.Init()
 7    // 注册 example handler
 8    api.RegisterExampleHandler(service.Server(), new(Example))
 9
10    // 注册 foo handler
11    api.RegisterFooHandler(service.Server(), new(Foo))
12
13    if err := service.Run(); err != nil {
14        log.Fatal(err)
15    }

. 测试

首先启动我们的api

1micro api --handler=api --namespace=go.micro.api  
微服务系列笔记之Mico Api详解

启动我们的服务端

1go run api.go
微服务系列笔记之Mico Api详解

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

测试bar

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

测试example

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

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

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

. 结语

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

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

END

今日推荐阅读

RabbitMQ系列笔记广播模式和路由模式  

RabbitMQ系列笔记入门篇

RabbitMQ系列笔记work模式

RabbitMQ系列笔记work模式

protoc语法详解及结合grpc定义服务

Golang中Model的使用

基于Nginx和Consul构建高可用及自动发现的Docker服务架构

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

▼关注我,一起成长

主要分享 学习心得、笔记、随笔▼

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

微服务系列笔记之Mico Api详解
原文  http://mp.weixin.qq.com/s?__biz=MzA4NTIyOTI3NQ==&mid=2247483862&idx=4&sn=3bb6078c950a075e1e7c97b33a7aca90
正文到此结束
Loading...