hello micro!

赶紧完成一个就micro的微服务吧~

micro为我们提供的微服务框架如下

这里面有很多角色,Micro API, Customer API, Customer Service 等等...

其中 Micro API是micro给我们提供的一个工具,是通过RPC调用我们模块的API和做一些负载均衡的作用,实际上Customer API, Customer Service是一组微服务,Customer API 收到 Micro API 转发的请求后,将RESTful转换成protobuf 通过gRPC调用发送给Customer Service做服务处理,然后又将返回protobuf数据转换成RESTful返回给用户。

在微服务架构中 一般称 API为RPC GateWay

GRPC Gateway

此指南帮助我们使用go-micro微服务中的grpc gateway。

grpc-gateway是一个protoc的一个插件。 它基于gRPC服务定义,并且提供一个将RESTful JSON API 转换成gRPC协议的反响代理服务。

我们使用go-grpc 去完成 后台服务, go-grpc 是一个为client/server将go-micro和gRPC结合的一个包裹。

代码案例

examples/grpc.

1 准备

=====> 我们需要做一些准备工作。

安装 protobuf

我们之前的章节已经安装过了protobuf环境

如果没有安装请尝试以下方法重新安装。

mkdir tmp
cd tmp
git clone https://github.com/google/protobuf
cd protobuf
./autogen.sh
./configure
make
make check
sudo make install

安装 protoc-gen-go 和 protoc-gen-grpc-gateway插件

go get -u github.com/micro/protobuf/protoc-gen-go
go get -u github.com/micro/go-grpc

2 构建hello 微服务

我们先在$GOPATH/src/ 下创建一个我们用来存放我们微服务们的主路径,micro框架的文档中都是用他们现成了,刚接触看起来真的一头雾水,所以我们还是自己重新来吧~~~

cd $GOPATH/src
mkdir micro_services

(1) 创建hello微服务protobuf协议 hello.proto

cd micro_services
mkdir hello
cd hello
mkdir proto
cd proto
touch hello.proto

编辑hello.proto文件

syntax = "proto3";

//包名 建议和 和服务名称一致
package go.micro.srv.hello;

//提供的模块
service Say {
        //提供的方法
        rpc Hello(Request) returns (Response) {}
}

message Request {
        string name = 1;
}

message Response {
        string msg = 1;
}

生成pb 文件

protoc --go_out=plugins=micro:. hello.proto

====>

关于 --go_out=plugins=micro 中的

protoc micro插件无法生效的解决方案

有可能我们的环境之前已经安装过了$GOPATH/src/github.com/golang/protobuf, 并且在$GOPATH/bin/中拥有了一个之前的
protoc-gen-go

而且跟 github.com/micro/protobuf

解决办法:

将$GOPATH/bin/protoc-gen-go删除,

将$GOPATH/src/github.com/golang/protobuf/删除

重新下载github.com/micro/protobuf

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

<====

(2) 创建hello微服务 --- srv.go

在microservices/hello/下创建 srv.go文件 相当于处理业务的核心模块。

package main

import (
    "log"
    "time"

    "github.com/micro/go-micro"
    hello "micro_services/hello/proto"

    "golang.org/x/net/context"
)

type Say struct{}

//实现Hello 方法
func (s *Say) Hello(ctx context.Context, req *hello.Request, rsp *hello.Response) error {
    log.Print("Received Say.Hello request")
    rsp.Msg = "Hello " + req.Name
    return nil
}

func main() {
    //创建一个micro service
    service := micro.NewService(
        //这里是当前服务的名称
        micro.Name("go.micro.srv.hello"),
        micro.RegisterTTL(time.Second*30),
        micro.RegisterInterval(time.Second*10),
    )

    // optionally setup command line usage
    service.Init()

    // 将hello protobuf中的服务注册到micro serivice中
    hello.RegisterSayHandler(service.Server(), new(Say))

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

(3) 创建hello api gateway --- srv.go

package main

import (
    "encoding/json"
    "log"
    "strings"

    "github.com/micro/go-micro"
    "github.com/micro/go-micro/errors"
    api "github.com/micro/micro/api/proto"
    hello "micro_services/hello/proto"

    "golang.org/x/net/context"
)

type Say struct {
    Client hello.SayClient
}

func (s *Say) Hello(ctx context.Context, req *api.Request, rsp *api.Response) error {
    log.Print("Received Say.Hello API request....")

    //可以从req中得到RESTful 参数等
    name, ok := req.Get["name"]
    if !ok || len(name.Values) == 0 {
        return errors.BadRequest("go.micro.api.hello", "Name cannot be blank")
    }

    //通过micro封装好的protobuf方法 通过rpc调用远程的Hello方法
    //这里是一个 protobuf 的 RPC调用
    //response作为返回值 返回值类型当然要参考hello.proto文件
    response, err := s.Client.Hello(ctx, &hello.Request{
        Name: strings.Join(name.Values, " "),
    })
    if err != nil {
        log.Print("client srv hello error....err = ", err)
        return err
    }

    //给micro API返回200 和message,这里貌似不需要修改
    rsp.StatusCode = 200
    b, _ := json.Marshal(map[string]string{
        "message": response.Msg,
    })
    rsp.Body = string(b)

    return nil
}

func main() {
    service := micro.NewService(
        //当前api的名称,一般都应该和对应的srv名称一样 ,只不过中的srv变成了api
        micro.Name("go.micro.api.hello"),
    )

    // parse command line flags
    service.Init()

    service.Server().Handle(
        service.Server().NewHandler(
            //具体要和哪个微服务通信,这个名称一定要和对应的微服务名称一致
            &Say{Client: hello.NewSayClient("go.micro.srv.hello", service.Client())},
        ),
    )

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

3 启动micro微服务

(1) 启动服务发现consul

consul agent -dev -enable-script-checks \
-bind=101.200.170.171 \
-config-dir ./consul.d/ \
-client 101.200.170.171

主要用于服务发现,因为micro默认依赖consul进行服务发现,每个基于micro完成的微服务都会向consul注册服务。

(2) 启动micro API

主要是负载均衡和对用户接受RESTful

micro --registry_address "101.200.170.171" \
api \
address "101.200.170.171:8080"

当前API监控 8080端口,所以用户的主入口是8080端口

(3) 启动hello API

进入micro_services/hello/文件下

go run api.go --registry_address "101.200.170.171:8500"

(4) 启动hello srvice

进入micro_services/hello/文件下

go run srv.go --registry_address "101.200.170.171:8500"

4 测试hello 方法

curl测试

curl http://101.200.170.171:8080/hello/say/hello?name=Aceld

结果

{"message":"Hello Aceld"}

浏览器测试

这样我们的Micro 的hello world就跑通了,但是如果再基于他写业务,还得继续研究他的其他接口了。

results matching ""

    No results matching ""