go-zero 微服務(wù)

2022-04-25 17:47 更新

在上一篇我們已經(jīng)演示了怎樣快速創(chuàng)建一個單體服務(wù),接下來我們來演示一下如何快速創(chuàng)建微服務(wù), 在本小節(jié)中,api部分其實(shí)和單體服務(wù)的創(chuàng)建邏輯是一樣的,只是在單體服務(wù)中沒有服務(wù)間的通訊而已, 且微服務(wù)中api服務(wù)會多一些rpc調(diào)用的配置。

前言

本小節(jié)將以一個訂單服務(wù)調(diào)用用戶服務(wù)來簡單演示一下,演示代碼僅傳遞思路,其中有些環(huán)節(jié)不會一一列舉。

情景提要

假設(shè)我們在開發(fā)一個商城項(xiàng)目,而開發(fā)者小明負(fù)責(zé)用戶模塊(user)和訂單模塊(order)的開發(fā),我們姑且將這兩個模塊拆分成兩個微服務(wù)

微服務(wù)的拆分也是一門學(xué)問,這里我們就不討論怎么去拆分微服務(wù)的細(xì)節(jié)了。

演示功能目標(biāo)

  • 訂單服務(wù)(order)提供一個查詢接口
  • 用戶服務(wù)(user)提供一個方法供訂單服務(wù)獲取用戶信息

服務(wù)設(shè)計(jì)分析

根據(jù)情景提要我們可以得知,訂單是直接面向用戶,通過http協(xié)議訪問數(shù)據(jù),而訂單內(nèi)部需要獲取用戶的一些基礎(chǔ)數(shù)據(jù),既然我們的服務(wù)是采用微服務(wù)的架構(gòu)設(shè)計(jì), 那么兩個服務(wù)(user, order)就必須要進(jìn)行數(shù)據(jù)交換,服務(wù)間的數(shù)據(jù)交換即服務(wù)間的通訊,到了這里,采用合理的通訊協(xié)議也是一個開發(fā)人員需要 考慮的事情,可以通過http,rpc等方式來進(jìn)行通訊,這里我們選擇rpc來實(shí)現(xiàn)服務(wù)間的通訊,相信這里我已經(jīng)對"rpc服務(wù)存在有什么作用?"已經(jīng)作了一個比較好的場景描述。 當(dāng)然,一個服務(wù)開發(fā)前遠(yuǎn)不止這點(diǎn)設(shè)計(jì)分析,我們這里就不詳細(xì)描述了。從上文得知,我們需要一個

  • user rpc
  • order api

兩個服務(wù)來初步實(shí)現(xiàn)這個小demo。

創(chuàng)建mall工程

如果你跑了單體的示例,里面也叫 go-zero-demo,你可能需要換一個父目錄。

$ mkdir go-zero-demo
$ cd go-zero-demo
$ go mod init go-zero-demo

說明:如無 cd 改變目錄的操作,所有操作均在 go-zero-demo 目錄執(zhí)行

創(chuàng)建user rpc服務(wù)

  • 創(chuàng)建user rpc服務(wù)

$ mkdir -p mall/user/rpc

  • 添加user.proto文件,增加getUser方法

$ vim mall/user/rpc/user.proto

增加如下代碼:

syntax = "proto3";

package user;

// protoc-gen-go 版本大于1.4.0, proto文件需要加上go_package,否則無法生成
option go_package = "./user";

message IdRequest {
    string id = 1;
}

message UserResponse {
    // 用戶id
    string id = 1;
    // 用戶名稱
    string name = 2;
    // 用戶性別
    string gender = 3;
}

service User {
    rpc getUser(IdRequest) returns(UserResponse);
}

  • 生成代碼 如未安裝 ?protoc?,?protoc-gen-go?,?protoc-gen-grpc-go? 你可以通過如下指令一鍵安裝:

$ goctl env check -i -f

注意: 1、每一個 ?*.proto?文件只允許有一個service error: only one service expected

$ cd mall/user/rpc
$ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.
Done.

  • 填充業(yè)務(wù)邏輯

$ vim internal/logic/getuserlogic.go
package logic

import (
    "context"

    "go-zero-demo/mall/user/rpc/internal/svc"
    "go-zero-demo/mall/user/rpc/types/user"

    "github.com/zeromicro/go-zero/core/logx"
)

type GetUserLogic struct {
    ctx    context.Context
    svcCtx *svc.ServiceContext
    logx.Logger
}

func NewGetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserLogic {
    return &GetUserLogic{
        ctx:    ctx,
        svcCtx: svcCtx,
        Logger: logx.WithContext(ctx),
    }
}

func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {
    return &user.UserResponse{
            Id:   "1",
            Name: "test",
    }, nil
}

創(chuàng)建order api服務(wù)

  • 創(chuàng)建 ?order api?服務(wù)

# 回到 go-zero-demo/mall 目錄
$ mkdir -p order/api && cd order/api

  • 添加api文件

$ vim order.api
type(
    OrderReq {
        Id string `path:"id"`
    }

    OrderReply {
        Id string `json:"id"`
        Name string `json:"name"`
    }
)
service order {
    @handler getOrder
    get /api/order/get/:id (OrderReq) returns (OrderReply)
}

  • 生成order服務(wù)

$ goctl api go -api order.api -dir .
Done.

  • 添加user rpc配置

$ vim internal/config/config.go
package config

import (
    "github.com/zeromicro/go-zero/zrpc"
    "github.com/zeromicro/go-zero/rest"
)

type Config struct {
    rest.RestConf
    UserRpc zrpc.RpcClientConf
}

  • 添加yaml配置

$ vim etc/order.yaml
Name: order
Host: 0.0.0.0
Port: 8888
UserRpc:
  Etcd:
    Hosts:
    - 127.0.0.1:2379
    Key: user.rpc

  • 完善服務(wù)依賴

$ vim internal/svc/servicecontext.go
package svc

import (
    "go-zero-demo/mall/order/api/internal/config"
    "go-zero-demo/mall/user/rpc/user"

    "github.com/zeromicro/go-zero/zrpc"
)

type ServiceContext struct {
    Config  config.Config
    UserRpc user.User
}

func NewServiceContext(c config.Config) *ServiceContext {
    return &ServiceContext{
        Config:  c,
        UserRpc: user.NewUser(zrpc.MustNewClient(c.UserRpc)),
    }
}

  • 添加order演示邏輯

給 getorderlogic 添加業(yè)務(wù)邏輯

$ vim internal/logic/getorderlogic.go
package logic

import (
    "context"
    "errors"

    "go-zero-demo/mall/order/api/internal/svc"
    "go-zero-demo/mall/order/api/internal/types"
    "go-zero-demo/mall/user/rpc/types/user"

    "github.com/zeromicro/go-zero/core/logx"
)

type GetOrderLogic struct {
    logx.Logger
    ctx    context.Context
    svcCtx *svc.ServiceContext
}

func NewGetOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) GetOrderLogic {
    return GetOrderLogic{
        Logger: logx.WithContext(ctx),
        ctx:    ctx,
        svcCtx: svcCtx,
    }
}

func (l *GetOrderLogic) GetOrder(req *types.OrderReq) (*types.OrderReply, error) {
    user, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdRequest{
        Id: "1",
    })
    if err != nil {
        return nil, err
    }

    if user.Name != "test" {
        return nil, errors.New("用戶不存在")
    }

    return &types.OrderReply{
        Id:   req.Id,
        Name: "test order",
    }, nil
}

啟動服務(wù)并驗(yàn)證

  • 啟動etcd

$ etcd

  • 下載依賴

# 在 go-zero-demo 目錄下
$ go mod tidy

  • 啟動user rpc

# 在 mall/user/rpc 目錄
$ go run user.go -f etc/user.yaml
Starting rpc server at 127.0.0.1:8080...

  • 啟動order api

# 在 mall/order/api 目錄
$ go run order.go -f etc/order.yaml
Starting server at 0.0.0.0:8888...

  • 訪問order api

$ curl -i -X GET http://localhost:8888/api/order/get/1
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 07 Feb 2021 03:45:05 GMT
Content-Length: 30

{"id":"1","name":"test order"}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號