micro简单使用

1.概述

gRPC(Google Remote Procedure Call)是一种高性能、跨语言的远程过程调用框架,为了简化操作,就有了micro

Micro 是一个基于 Go 的微服务框架,旨在简化构建分布式系统的过程。它提供了一组工具和库,用于处理常见的分布式系统问题,如服务发现、负载均衡、消息传递和配置管理等。

这里介绍如何简单使用micro,并使用consul作为注册中心。

为了方便,docker安装consul。

运行consul

docker run -d -p 8500:8500 --restart=always --name consul consul:1.8.8 agent -server -bootstrap -ui -node=consul_node_01 -client='0.0.0.0'

访问

http://localhost:8500

 

2.简单使用

下载go-micro

go install github.com/go-micro/cli/cmd/go-micro@latest

 

下载proto相关(使用过grpc上述proto相关都应该下过)

go get -u google.golang.org/protobuf/proto
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

 

再下载一个micro相关的proto

go install github.com/go-micro/generator/cmd/protoc-gen-micro@latest

 

服务端(服务注册)

先创建项目micro-server

 

创建服务端

go-micro new service helloworld

 

生成的目录结构如下

 

默认的proto文件写了4个方法,正是grpc的4种服务,以及一些自定义的request和response

syntax = "proto3";

package helloworld;

option go_package = "./proto;helloworld";

service Helloworld {
  rpc Call(CallRequest) returns (CallResponse) {}
  rpc ClientStream(stream ClientStreamRequest) returns (ClientStreamResponse) {}
  rpc ServerStream(ServerStreamRequest) returns (stream ServerStreamResponse) {}
  rpc BidiStream(stream BidiStreamRequest) returns (stream BidiStreamResponse) {}
}

message CallRequest {
  string name = 1;
}

message CallResponse {
  string msg = 1;
}

message ClientStreamRequest {
  int64 stroke = 1;
}

message ClientStreamResponse {
  int64 count = 1;
}

message ServerStreamRequest {
  int64 count = 1;
}

message ServerStreamResponse {
  int64 count = 1;
}

message BidiStreamRequest {
  int64 stroke = 1;
}

message BidiStreamResponse {
  int64 stroke = 1;
}

 

这里修改一下,使用我们自定义的方法

修改proto/helloworld.proto

syntax = "proto3";

package helloword;

option go_package = "./proto;helloworld";

service Helloworld{
  //一元调用
  rpc SayHello(SayRequest) returns(SayResponse){}
}
message SayRequest{
  string name = 1;
  string msg = 5;
}
message SayResponse{
  string msg = 5;
}

 

生成proto文件

protoc --proto_path=. --micro_out=. --go_out=:. ./proto/helloworld.proto

 

如图生成如下文件

 

下载相关插件

go mod tidy

 

同样的handle包下默认实现了默认的proto文件的4个方法,所以我们改了proto文件,也要改handle包下的helloword.go文件

默认的helloword.go文件

package handler

import (
    "context"
    "io"
    "time"

    "go-micro.dev/v4/logger"

    pb "helloworld/proto"
)

type Helloworld struct{}

func (e *Helloworld) Call(ctx context.Context, req *pb.CallRequest, rsp *pb.CallResponse) error {
    logger.Infof("Received Helloworld.Call request: %v", req)
    rsp.Msg = "Hello " + req.Name
    return nil
}

func (e *Helloworld) ClientStream(ctx context.Context, stream pb.Helloworld_ClientStreamStream) error {
    var count int64
    for {
        req, err := stream.Recv()
        if err == io.EOF {
            logger.Infof("Got %v pings total", count)
            return stream.SendMsg(&pb.ClientStreamResponse{Count: count})
        }
        if err != nil {
            return err
        }
        logger.Infof("Got ping %v", req.Stroke)
        count++
    }
}

func (e *Helloworld) ServerStream(ctx context.Context, req *pb.ServerStreamRequest, stream pb.Helloworld_ServerStreamStream) error {
    logger.Infof("Received Helloworld.ServerStream request: %v", req)
    for i := 0; i < int(req.Count); i++ {
        logger.Infof("Sending %d", i)
        if err := stream.Send(&pb.ServerStreamResponse{
            Count: int64(i),
        }); err != nil {
            return err
        }
        time.Sleep(time.Millisecond * 250)
    }
    return nil
}

func (e *Helloworld) BidiStream(ctx context.Context, stream pb.Helloworld_BidiStreamStream) error {
    for {
        req, err := stream.Recv()
        if err == io.EOF {
            return nil
        }
        if err != nil {
            return err
        }
        logger.Infof("Got ping %v", req.Stroke)
        if err := stream.Send(&pb.BidiStreamResponse{Stroke: req.Stroke}); err != nil {
            return err
        }
    }
}

 

修改后

package handler

import (
    "context"
    "go-micro.dev/v4/logger"
    pb "helloworld/proto"
)

type Helloworld struct{}

func (e *Helloworld) SayHello(ctx context.Context, req *pb.SayRequest, rsp *pb.SayResponse) error {
    logger.Infof("Received Helloworld request: %v", req)
    rsp.Msg = "Hello " + req.Name
    return nil
}

 

引入consul包

go get github.com/go-micro/plugins/v4/registry/consul

 

修改main.go,注册到consul

package main

import (
    "github.com/go-micro/plugins/v4/registry/consul"
    "go-micro.dev/v4"
    "go-micro.dev/v4/logger"
    "go-micro.dev/v4/registry"
    "helloworld/handler"
    pb "helloworld/proto"
)

var (
    service = "hello-server"
    version = "1.0.0"
)

func main() {
    //集成consul
    consulReg := consul.NewRegistry(
        registry.Addrs("127.0.0.1:8500"),
    )
    // Create service
    srv := micro.NewService(
        micro.Address("127.0.0.1:9090"),
        micro.Name(service),
        micro.Version(version),
        //注册consul
        micro.Registry(consulReg),
    )
    srv.Init(
        micro.Name(service),
        micro.Version(version),
    )

    // Register handler
    if err := pb.RegisterHelloworldHandler(srv.Server(), new(handler.Helloworld)); err != nil {
        logger.Fatal(err)
    }
    // Run service
    if err := srv.Run(); err != nil {
        logger.Fatal(err)
    }
}

 

运行

可以看到成功注册到了consul

 

 

客户端代码(服务发现)

创建一个新项目micro-client

生成客户端代码

go-micro new client helloworld

代码结构如下:

在这里生成的客户端文件夹名字是helloworld-client

将服务端的proto文件夹拷贝

删除gomod文件,重新初始化

go mod init helloworld-client
go mod tidy

 

如果出现如下错误

导入即可

go get go-micro.dev/v4/

 

打开main.go替换一下包名,毕竟是服务端拷贝的会出现包名不一致

替换如下:

 

导入consul

go get github.com/go-micro/plugins/v4/registry/consul

 

main.go是自动生成的代码,会和我们的proto定义的方法不一致,更改如下:

package main

import (
    "context"
    "github.com/go-micro/plugins/v4/registry/consul"
    "go-micro.dev/v4"
    "go-micro.dev/v4/logger"
    "go-micro.dev/v4/registry"
    pb "helloworld-client/proto"
    "time"
)

var (
    //根据service从consul发现
    service = "hello-server"
    version = "latest"
)

func main() {
    //集成consul
    consulReg := consul.NewRegistry(
        registry.Addrs("127.0.0.1:8500"),
    )
    // Create service
    srv := micro.NewService(
        //注册consul
        micro.Registry(consulReg),
    )
    srv.Init()

    // 创建客户端实例
    c := pb.NewHelloworldService(service, srv.Client())
    for {
        // Call service
        rsp, err := c.SayHello(context.Background(), &pb.SayRequest{
            Name: "Dreams",
            Msg: "Hello! This is Client",
        })
       if err != nil {
           logger.Fatal(err)
       }

       logger.Info(rsp)

       time.Sleep(1 * time.Second)
    }
}

运行server项目,再运行client项目

服务端等待

客户端发送消息并成功接收到消息

服务端成功接收到消息

 

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇