go-zero微服务实战——基本环境搭建

这篇具有很好参考价值的文章主要介绍了go-zero微服务实战——基本环境搭建。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

项目架构来源于go-zero实战:让微服务Go起来。此对该项目有所删减,相对简单适合初学者。

省去了项目中每个服务占用独立docker的过程,省略了docker-compose的构建过程。每个服务是一个独立的程序不依赖与容器。

环境搭建

  1. 安装goctl
go install github.com/zeromicro/go-zero/tools/goctl@latest
  1. 安装protoc
goctl env check --install --verbose --force
  1. 安装go-zero
go get -u github.com/zeromicro/go-zero@latest
  1. 生成api标准api服务
goctl api new apiservice
  1. 生成rpc服务
goctl rpc new rpcservice

生成代码后go mod tidy下载所需依赖。

apiservice目录下的apiservicelogic.go27行后修改为如下图所示代码:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

删除apiservice目录下etc下的配置文件,在主程序中做如何修改如下修改,直接配置方便一些:

func main() {

	var c config.Config
	c.Host = "0.0.0.0"
	c.Port = 8000

	server := rest.MustNewServer(c.RestConf)
	defer server.Stop()

	ctx := svc.NewServiceContext(c)
	handler.RegisterHandlers(server, ctx)

	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
	server.Start()
}

api服务统一为8000系列的端口。

rpcservice目录下的yaml配置文件端口修改为9000系。主函数做如下修改:

func main() {
	var c config.Config
	c.ListenOn = "0.0.0.0:9000"
	c.Mode = "dev"
	ctx := svc.NewServiceContext(c)

	s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
		rpcservice.RegisterRpcserviceServer(grpcServer, server.NewRpcserviceServer(ctx))

		if c.Mode == service.DevMode || c.Mode == service.TestMode {
			reflection.Register(grpcServer)
		}
	})
	defer s.Stop()

	fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
	s.Start()
}

启动程序

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

浏览器访问

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

rpc客户端访问

新项目复制两个pb文件,编写客户端主程序。

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"rpcclient/rpcservice"
)

func main() {
	//配置连连接参数(无加密)
	dial, _ := grpc.Dial("localhost:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
	defer dial.Close()
	//创建客户端连接
	client := rpcservice.NewRpcserviceClient(dial)
	//通过客户端调用方法
	res, _ := client.Ping(context.Background(), &rpcservice.Request{Ping: "xiaoxu"})
	fmt.Println(res.Pong)

}

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

go-zero api服务构建

整合mysql数据库

构建如项目上的4个服务。4个服务都是上一节构建基本项目为基础的gitee地址

整合数据库就不再过多赘述了,整合xorm框架,返回数据库引擎即可,如下:

xorm实战——结构体映射到实现数据库操作

import (
	"fmt"

	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
)

var Engine *xorm.Engine

func init() {
	var err error
	e, err := xorm.NewEngine("mysql", "root:root@/zerotest?charset=utf8")
	if err != nil {
		fmt.Println("数据库连接失败!")
	}
	// err的错误处理
	Engine = e
}

构建mysql数据库后在其他包下通过库名.Engine即可使用数据库引擎。

创建数据库

CREATE TABLE `order` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `order_id` varchar(100) NOT NULL COMMENT '订单编号',
  `type` tinyint DEFAULT NULL COMMENT '订单类型',
  `customer_id` int DEFAULT NULL COMMENT '用户编号',
  `amount` int DEFAULT NULL COMMENT '数量',
  `payment` tinyint DEFAULT NULL COMMENT '支付方式',
  `status` tinyint DEFAULT NULL COMMENT '状态',
  `create_time` varchar(100) DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表';

控制器逻辑实现

新建logic目录

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

创建订单逻辑类

type orderLogic struct{}

var OrderLogic orderLogic

// 创建订单
func (this orderLogic) Create(param models.Order) error {
	param.Id = 0
	_, err := db.Engine.Insert(param)
	if err != nil {
		fmt.Printf("logic module create err:%v", err)
		return err
	}
	return nil
}

//db是构建服务器引擎的包

控制器调用逻辑代码

// create
func OrderCreateController() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//获取请求参数
		var req models.Order
		err := httpx.ParseJsonBody(r, &req)
		if err != nil {
			//fmt.Printf("ordercontoller err:%v", err)
			httpx.WriteJson(w, 500, fmt.Sprintf("ordercontoller err:%v", err))
			return
		}
		//******************//
		err = orderlogic.OrderLogic.Create(req)
		//******************//
		if err != nil {
			//fmt.Printf("order create err:%v", err)
			httpx.WriteJson(w, 500, fmt.Sprintf("order create err:%v", err))
			return
		}
		httpx.OkJson(w, map[string]string{"code": "200", "message": "插入成功!"})

	}
}

Create方法不使用结构体模拟类,直接是一个函数也是可以的,但是函数就不能重名了,在微服务中可以为单个函数,在单纯的web服务中还是用类实现比较好。

部分代码:

// create
func OrderCreateController() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//获取请求参数
		var req models.Order
		err := httpx.ParseJsonBody(r, &req)
		if err != nil {
			//fmt.Printf("ordercontoller err:%v", err)
			httpx.WriteJson(w, 500, fmt.Sprintf("ordercontoller err:%v", err))
			return
		}
		err = orderlogic.OrderLogic.Create(req)
		if err != nil {
			//fmt.Printf("order create err:%v", err)
			httpx.WriteJson(w, 500, fmt.Sprintf("order create err:%v", err))
			return
		}
		httpx.OkJson(w, map[string]string{"code": "200", "message": "插入成功!"})

	}
}

// update
func OrderUpdateController() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req models.Order
		err := httpx.ParseJsonBody(r, &req)
		if err != nil {
			httpx.WriteJson(w, 500, fmt.Sprintf("update err:%v", err))
			return
		}
		err = orderlogic.OrderLogic.Update(req)
		if err != nil {
			//...
			return
		}
		httpx.OkJson(w, map[string]string{"code": "200", "message": "更新成功!"})

	}
}

//Remove

func OrderRemove() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req models.Order
		err := httpx.ParseJsonBody(r, &req)
		if err != nil {
			httpx.WriteJson(w, 500, fmt.Sprintf("remove err%v", err))
			return
		}
		err = orderlogic.OrderLogic.Remove(req)
		if err != nil {
			//...
			return
		}
		httpx.OkJson(w, map[string]string{"code": "200", "message": "删除成功!"})
	}
}

//List

func OrderList() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		res, err := orderlogic.OrderLogic.List()
		if err != nil {
			//...
			return
		}
		httpx.OkJson(w, res)
	}
}

逻辑层直接省略了,就是xorm对mysql的CURD操作。

注册路由

func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
	server.AddRoutes(
		[]rest.Route{
			{
				Method:  http.MethodGet,
				Path:    "/from/:name",
				Handler: ApiserviceHandler(serverCtx),
			},
			//自定义路由
			{
				Method: http.MethodPost,
				Path: "/create",
				Handler: OrderCreateController(),
			},
			{
				Method: http.MethodPost,
				Path: "/update",
				Handler: OrderUpdateController(),
			},
			{
				Method: http.MethodPost,
				Path: "/remove",
				Handler: OrderRemove(),
			},
			{
				Method: http.MethodPost,
				Path: "/list",
				Handler: OrderList(),
			},
		},
	)
}

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
综上所属,已经成功的构建了一个web服务,包括对订单order的基本操作。

如果不想手写这莫多代码,可以看看zero的api语法,直接使用api文件一键生成更加方便。

go-zero rpc服务构建

在rpc远程调用中主要用于rpc服务器注册本地的方法,实现服务器之间的内部调用。在上述服务中,都是沿用了插件生成的目录,仅修改了部分配置文件。可以参考如下连接的目录结构层次清晰。

go-zero实战

删除旧的rpc服务的所有目录,保留proto文件,添加如下内容:

syntax = "proto3";

package rpcservice;
option go_package="./rpcservice";

message Request {
  string ping = 1;
}

message Response {
  string pong = 1;
}

service Rpcservice {
  rpc Ping(Request) returns(Response);
  // 自定义方法区
  rpc Create (Request) returns (Response);
  rpc Update (Request) returns (Response);
  rpc Remove (Request) returns (Response);
  rpc Detail (Request) returns (Response);
  rpc List (Request) returns (Response);
}

注意这里不再是goctl rpc new [name]了,该命令是一键生成rpc标准服务命令,而需要自定义rpc服务即根据编写的.proto文件生成服务需要使用protobuf插件命令。

protoc-gen-go,protoc-gen-go-grpc

这两个插件在grpc服务中一般是需要独立安装的,但是在go-zero中goctl集成了这两个插件。

protoc --go_out=. *.proto
protoc --go-grpc_out=. *.proto

以下是自定义rpc服务部分,goctl生成直接跳过

运行完指令后在proto文件指定的目录生成了grpc服务源码,如下

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

注意如果之前已经使用了goctl rpc命令,那么目录下不止有这两个文件,建议删除goctl生成的文件自定义构建,因为许多用不着到。goctl生成的代码主要是结合了zrpc.RpcServerConf的配置,即config目录下的对象,如下:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
在goctl生成的代码中也是支持flag库的,如下,这里后续将会改成静态的省去配置文件。
微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

goctl生成部分

通过两个命令生成rpc服务文件,如下:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

在生成的代码中已经具备了逻辑层的方法,如下:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

修改主程序注释调用flag参数获取功能,原因是api服务和rpc服务中都有独立的yaml文件这是不合理的,两个flag参数获取存在冲突,所以将两个都注册掉改为静态配置,后续可以改为一个配置文件。

//注释掉flag获取参数的部分
func main() {
	flag.Parse()

	var c config.Config
	// conf.MustLoad(*configFile, &c)
	c.ListenOn = "0.0.0.0:9000"
	c.Name = "order.rpc"
	ctx := svc.NewServiceContext(c)
	s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
		rpcservice.RegisterRpcserviceServer(grpcServer, server.NewRpcserviceServer(ctx))

		if c.Mode == service.DevMode || c.Mode == service.TestMode {
			reflection.Register(grpcServer)
		}
	})
	defer s.Stop()

	fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
	s.Start()
}

修改rpc服务的逻辑如下所示:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
编写客户端访问rpc服务

import (
	"context"
	"fmt"
	"rpcclient/rpcservice"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	//配置连连接参数(无加密)
	dial, _ := grpc.Dial("localhost:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
	defer dial.Close()
	//创建客户端连接
	client := rpcservice.NewRpcserviceClient(dial)
	//通过客户端调用方法
	res, err := client.Ping(context.Background(), &rpcservice.Request{ReqJson: "xiaoxu"})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(res)

}

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
成功访问,ping的案例是goctl已经实现了的,虽然早proto中编写了自定义的方法,如下

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
但是却仍然无法调用,回报未继承的错误,在客户端加入如下代码:

//order list
r, err := client.List(context.Background(), &rpcservice.Request{})
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(r.ResJson)

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

List not implemented该错误的原因时虽然存在该方法名,但方法没有方法体,也就说函数没有将处理逻。

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
在服务端通过反射获取到Rpcservice_Ping_FullMethodName的Ping方法,也就是/rpcservice.Rpcservice/Ping的Ping方法。如下图

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

该方法就是生成文件的server目录下包的方法,如下:

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

官方提供的方法ping调用了生成的logic的ping方法,其实就是实现了逻辑的解耦,将逻辑功能分隔开来。如下所示,logic层部分只写逻辑处理,在serve下调用逻辑处理部分函数。

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero
微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

当然不论如何解耦,核心还是server目录的文件,必须在此处注册逻辑函数,才可以在rpc武器生成函数实例,客户端才可以成功调用。

该方法实际上也是proto中定义的方法的一个重写过程,是接口的是实现。

注册自定义函数

//list 继承
func (s *RpcserviceServer) List(ctx context.Context,in *rpcservice.Request) (*rpcservice.Response, error) {
	//r, err := logic.List(in)
	o, err := orderlogic.OrderLogic.List()
	if err != nil {
		fmt.Printf("rpc err:%v", err)
		return &rpcservice.Response{}, err
	}
	//o 赚json字符串
	josnstr, _ := json.Marshal(o)
	return &rpcservice.Response{ResJson: string(josnstr)}, nil
}

上面代码逻辑部分一起写在rpc方法注册的函数中,当逻辑代码多是就会十分冗余,最好将逻辑部分提取出来封装在新函数中,在注册是调用新方法即可,想官方提供的模板一样。

服务端注册成功后,服务端调用,代码如下:

package main

import (
	"context"
	"fmt"
	"rpcclient/rpcservice"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	//配置连连接参数(无加密)
	dial, _ := grpc.Dial("localhost:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
	defer dial.Close()
	//创建客户端连接
	client := rpcservice.NewRpcserviceClient(dial)
	//通过客户端调用方法
	res, err := client.Ping(context.Background(), &rpcservice.Request{ReqJson: "xiaoxu"})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(res)

	//order list
	r, err := client.List(context.Background(), &rpcservice.Request{})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(r.ResJson)

}

微服务环境搭建,# go-zero,golang,微服务,开发语言,go-zero

别忘了克隆_grpc.pbpb文件。

到此服务order已经可以同时提供api服务和rpc服务了。

gitee地址:https://gitee.com/fireapproval/xiaoxu/tree/xiaoxu/go/go-zero-test文章来源地址https://www.toymoban.com/news/detail-729772.html

到了这里,关于go-zero微服务实战——基本环境搭建的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • go-zero的服务发现源码阅读

    服务发现原理与grpc源码解析_wangxiaoangg的博客-CSDN博客   go-zero rpc demo官方文档:rpc编写与调用 | go-zero 目录 一 服务注册 1. 创建rpc服务 2. 启动rpc服务 3. registerEtcd做了什么 4. discov.NewPublisher 服务发布者 二 服务发现 1.定义注册resolver 2.解析etcd地址创建链接 3.update方法 在看rp

    2024年02月06日
    浏览(60)
  • go-zero的rpc服务案例解析

    go-zero的远程调用服务是基于gRpc的gRPC教程与应用。 zero使用使用gRpc需要安装 protoc 插件,因为gRpc基于protoc插件使用protocol buffers文件生成rpc服务器和api的代码的。 gRPC 的代码生成还依赖 protoc-gen-go,protoc-gen-go-grpc 插件来配合生成 Go 语言的 gRPC 代码。 也可以使用go get命令安装

    2024年02月13日
    浏览(74)
  • go-zero学习 第三章 微服务

    1.1 API服务模块 goctl 使用 api 文件生成 api服务 命令: 1.2 RPC服务模块 goctl 使用 protoc 文件生成 rpc服务 命令: 注意: --go_out 、 --go-grpc_out 、 --zrpc_out 三者配置的路径需要完全一致,否则会报下列错误。 基础代码:已生成基本的API服务、RPC服务。 这里以API服务调用RPC服务的登

    2024年02月16日
    浏览(72)
  • 【go-zero】go-zero阿里云oss 前端上传文件到go-zero API服务 并在k8s pod中创建文件 并推送到阿里云oss 最佳实践

    问题:在本地通过上传文件,然后将文件推送到aliyun的oss中,是没问题的 但是部署到了k8s中,则出现了问题,一直报错没有创建的权限 思路:开始认为应该将该文件挂载到configmap中,然后通过这种方式修改了deployment和dockerfile。最终发现应该是go的创建文件路径方式搞错了,

    2024年02月13日
    浏览(46)
  • 微服务框架 go-zero logx 日志组件剖析

    上一篇我们说到咱们还剩下 addTenant 功能还未实现,不知道有没有兄弟感兴趣去实验一波的,本篇文章进行简要补充 根据上一篇文章分析,其实我们只需要执行如下几步即可: 编写 tenant.api,提供外部 addTenant 的 http 接口 编写 tenant.api 提供一个 POST http 的接口 / api /tenant/addt

    2024年02月11日
    浏览(49)
  • Go-Zero微服务快速入门和最佳实践(一)

    并发编程和分布式微服务 是我们Gopher升职加薪的关键。 毕竟Go基础很容易搞定,不管你是否有编程经验,都可以比较快速的入门Go语言进行简单项目的开发。 虽说好上手,但是想和别人拉开差距,提高自己的竞争力, 搞懂分布式微服务和并发编程还是灰常重要的,这也是我

    2024年04月28日
    浏览(41)
  • 微服务架构|go-zero 的自适应熔断器

    原文链接: go-zero 的自适应熔断器 上篇文章我们介绍了微服务的限流,详细分析了计数器限流和令牌桶限流算法,这篇文章来说说熔断。 熔断和限流还不太一样,限流是控制请求速率,只要还能承受,那么都会处理,但熔断不是。 在一条调用链上,如果发现某个服务异常,

    2024年02月10日
    浏览(52)
  • go-zero/grpc的rpc服务间传递额外数据

    go-zero/grpc的rpc服务间传递额外数据 2024/02/18 客户端: 初始化 md 也可如下方式: 追加新的如下: 也可使用 md 的 Set 和 Append 方法追加: 服务端: 注意 key 都会被转为小写,即使客户端为大写: 而且 key 只能由 数字、字母和三个特殊字符“-_.”组成,大写字母会自动被转为小写

    2024年02月19日
    浏览(60)
  • GoZero微服务个人探索之路(三)Go-Zero官方rpc demo示例探究

    两个文件均为protoc-gen-go-grpc自动生成 构成一个完整的 gRPC 服务的定义和实现 demo.go goctl生成的客户端代码 Request 和 Response 别名: 定义了 Request 和 Response 两个别名,实际上是从 demo 包中导入的对应的消息类型。 Demo 接口: 定义了一个 Demo 接口,其中包含了调用 gRPC 服务中 P

    2024年01月18日
    浏览(54)
  • 基于go-zero的api服务刨析并对比与gin的区别

    官网go-zero go-zero是一个集成了各种工程实践的微服务框架,集多种功能于一体,如服务主要的API服务,RPC服务等。除了构建微服务工程外,zero也是一款性能优良的web框架,也可以构建单体web应用。 更多移步www.w3cschool.cn/go-zero。 go的web框架是很多的,例如github较为流行的有:

    2024年02月13日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包