11

简单易懂的golang[go-micro]微服务

 4 years ago
source link: https://segmentfault.com/a/1190000022240494
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

微服务是一个新兴的软件架构,就是把一个大型的单个应用程序和服务拆分为数十个的支持微服务。一个微服务的策略可以让工作变得更为简便,它可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等级协议。

一般的微服务工作流程都可以用写明这种图来表达。

fAZrEf6.png!web

  1. 先把自己的服务注册到注册中心
  2. 客户端调用的时候去注册中心查询调用的服务的服务器列表
  3. 得到服务列表,随机调取一台进行远程协程

我们这里的注册中心使用的是ETCD

1.为什么不选择Redis?

ps:首先注册中心的存放必须保证稳定,不可缺失。要不注册中心挂了,你要一个个服务的去重启?然后把它们从新注册到注册中心?这工作量你想想都不愿意更别说运维了。

2.为什么不选择ZooKeeper ?

ps: ZooKeeper 因为Zookeeper 只提供了 c++ 和 java 的接口,维护难,成功高,etcd简单。

这里有一篇 《etcd部署》 https://www.jianshu.com/u/ae33b518429a ,看来你就知道有多简单了

我这里选择的grpc

ps:使用grpc最打的特性是他支持多语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。

它是通过ProtoBuf 进行数据直接的通信的,比如日本人和我们聊天,我们不会日语,这个适合刚好有一个朋友会日语,那么这个朋友就把日语转为中文告诉我们。

所以我们还需要学学ProtoBuf 的语法,不过一般来说记住一些格式即可

# greeter.proto
syntax = "proto3"; #使用proto3

service Greeter {  #这个对象的
    rpc Hello(HelloRequest) returns (HelloResponse) {}  #这个拥有那些方法
}

message HelloRequest {    #消息参数 注意 name = 1,1 后面的那个数字不能重复
    string name = 1;
}

message HelloResponse {  #响应参数 注意 greeting = 2,2 后面的那个数字不能重复,名字随便你们起,这么起只不过是为了好认
    string greeting = 2;
}

编写玩这个文件之后,我们需要执行以下代码进行便宜,把他转化为golang文件。

protoc -I . --micro_out=. --go_out=. path/to/greeter.proto

我们接下来后得到以下两个文件

uAfEFj7.png!web

接下来我们就要做服务端的代码了

我这里使用的go-micro的包

这个包的设计理念和我们上面所说的工作流程差不多,而且经验了 3年的考验,我是赖人主义,而且这包也比较轻量,所以就直接拿来用了。

EB7ZJ3q.png!web

他的设计流程如上,分为客户端和服务端,然后客户端和服务端通过这5个接口进行通信。

服务端代码

之前说过要使用etcd做注册中心的存储,所以我们需要这么这么做

package main

import (
    "context"
    "fmt"
    "github.com/micro/go-micro/v2"
    "github.com/micro/go-micro/v2/registry"
    "github.com/micro/go-micro/v2/registry/etcd" #注意这里go-micro的顺序
    "molei.rainbowmorel.com/micro-service/proto"
)

#这里对应这里的代码  service Greeter {  #这个对象的
#    rpc Hello(HelloRequest) returns (HelloResponse) {}  #这个拥有那些方法
#}
type Greeter struct{} 

func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error {
    rsp.Greeting = "Hello " + req.Name
    return nil
}

func main() {
        #定义etcd的注册
    reg := etcd.NewRegistry(func(options *registry.Options) {
        options.Addrs = []string{
            "192.168.33.130:2379",
        }
    })

    service := micro.NewService(
        micro.Registry(reg), 
        micro.Name("greeter")) #这两部是关键,网上说的其他东西都可以不看,但两个必须要有

    service.Init()
    proto.RegisterGreeterHandler(service.Server(), new(Greeter))  //protoc有多少个服务器,你就在这里写多少个

    if err := service.Run(); err != nil {
        fmt.Println(err)
    }
}

客户端代码

package main

import (
    "context"
    "fmt"
    "github.com/micro/go-micro/v2"
    "github.com/micro/go-micro/v2/registry"
    "github.com/micro/go-micro/v2/registry/etcd"
    "log"
    "molei.rainbowmorel.com/micro-client/proto"
)

func main() {
    reg := etcd.NewRegistry(func(options *registry.Options) {
        options.Addrs = []string{
            "192.168.33.130:2379",
        }
    })

    service := micro.NewService(
        micro.Registry(reg),
        micro.Name("greeter"))

    service.Init()

    greeter := proto.NewGreeterService("greeter", service.Client())

    rsp, err := greeter.Hello(context.TODO(), &proto.Request{Name: "莫雷"})
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(rsp.GetGreeting())
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK