go-zero

news2024/9/23 9:21:04

目录

  • 引入
    • 开发派系
      • 标准库/自研派系——不要让框架束缚开发
      • web框架派系——gin+grpc
      • 大一统框架
  • go-zero
  • go-zero快速实现一个微服务
    • user service
    • order api server
    • 启动
  • goctl
    • 安装
    • 生成的api网关目录
    • 生成的pb目录
    • api语法
      • syntax
      • import语法块
      • info
      • type
      • service
      • 注释
    • 命令大全

引入

在这里插入图片描述
该图片来自微软开源的一个容器商城项目:eShopOnContainers,其中红框部分就是各个微服务模块。

每一个微服务都是一个独立的生态,比较直观的一点是各自拥有独立的数据库。

微服务化后,带来了诸多好处,比如弹性,敏捷,灵活扩展,易于部署,可重用代码等。

但也带来了复杂性,让整个架构变得不易于维护,所以诞生出来很多组件用于辅助,这些组件同样成为了微服务架构中的一员:

  1. 服务网关:确保服务提供者对客户端的透明,这一层可以进行反向路由,安全认证,灰度发布,日志监控等前置动作。
    在这里插入图片描述
  2. 服务发现:注册并维护远程服务及服务提供者的地址,供服务消费者发现和调用,如:etcd,consul等
  3. 服务框架:实现了rpc框架,包含服务接口描述和实现,向注册中心发布服务等功能,比如grpc等
  4. 服务监控:对服务消费者与提供者之间的的调用情况进行监控和数据展示比如:普罗米修斯(prometheus)
  5. 服务追踪:记录每个请求的为服务器调用完整链路,以便进行问题定位和故障分析,比如jeager,zipkin等
  6. 服务治理:服务治理就是通过一系列的手段来保证在各种意外情况下,服务调用仍然能够正常进行,这些手段包括熔断,隔离,限流,降级,负载均衡等,比如:Sentinel等.
  7. 基础设施:用以提供服务底层的基础数据服务,比如分布式消息队列,日志存储,数据库,缓存,文件服务器,搜索集群。比如:kafka,mysql,pgsql,mongodb,redis,minio,elasticSearch等。
  8. 分布式配置中心:统一配置,比如nacos,consul,zk,apollo等
  9. 分布式事务:dtm,seata等
  10. 容器以及容器编排:docker,k8s等
  11. 定时任务

综上,容器时微服务架构的绝佳示例,现代云原生应用使用容器来构建微服务。

开发派系

标准库/自研派系——不要让框架束缚开发

  1. 对于go标准库的强大(稳定,高性能),让很多开发者不使用框架也可以写出高效的应用程序。
  2. 微服务的基础是通信,也就是rpc框架的选择,大部分会选择grpc或者基于grpc的基础进行自研rpc框架的开发
  3. 其他组件需要的时候,进行集成就可以了,而不是非得用某个框架定义的组件。
  4. 如果部署采用k8s,并且使用服务网格,比如Istio来处理,那么开发者只需要关心业务逻辑即可,不需要关心服务发现,熔断,流量控制,负载均衡。

web框架派系——gin+grpc

  1. 由于标准库到web框架开发仍然需要一定量的开发工作,所以选择成熟的gin框架,出现了grpc+gin核心,其他组件集成进来的微服务框架。
  2. gin在这里可以作为grpc网关使用,写一些限流中间件,认证中间件。通过在api view中调用内部的微服务,对外提供服务。
  3. 同样可以使用k8s+istio.

大一统框架

  1. 使用框架能减轻工作量,达到快速开发的目的。代价就是遵循框架的规则。
  2. go的微服务框架比较多,如:go-zero,go-micro,go-kit…
  3. go-zero是一个不错的选择,其社区活跃,文档齐全。

go-zero

在这里插入图片描述

go-zero 是一个集成了各种工程实践的包含 web 和 rpc 框架,有如下主要特点:

  1. 强大的工具支持,尽可能少的代码编写
  2. 极简的接口
  3. 完全兼容 net/http
  4. 支持中间件,方便扩展
  5. 高性能
  6. 面向故障编程,弹性设计
  7. 内建服务发现、负载均衡
  8. 内建限流、熔断、降载,且自动触发,自动恢复
  9. API 参数自动校验
  10. 超时级联控制
  11. 自动缓存控制
  12. 链路跟踪、统计报警等
  13. 高并发支撑,稳定保障了疫情期间每天的流量洪峰

在这里插入图片描述

go-zero快速实现一个微服务

  1. 订单服务(order)提供一个查询接口
  2. 用户服务(user)提供一个方法供订单服务获取用户信息

user service

  1. 创建user目录

  2. 编写proto文件:

    syntax = "proto3";
    
    package user;
    
    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);
    }
    
  3. 使用goctl生成go-zero模板和pb文件:goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.

  4. 实现查询用户的功能:

    func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {
    	return &user.UserResponse{
    		Id:     in.Id,
    		Name:   "generalzy",
    		Gender: "武装直升机",
    	}, nil
    }
    

    在这里插入图片描述

  5. go build编译

order api server

  1. 创建order目录

  2. 编写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)
    }
    
  3. 使用goctl生成api:goctl api go -api order.api -dir .

  4. 配置user config:

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

    在这里插入图片描述

  5. 配置yaml:

    Name: order
    Host: 0.0.0.0
    Port: 8888
    UserRpc:
      Etcd:
        Hosts:
          - 127.0.0.1:2379
        Key: user.rpc
    
  6. 完善服务依赖(将user放入到order的上下文)

    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)),
    	}
    }
    

    在这里插入图片描述

  7. 编写order业务逻辑

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

	if u.Name != "generalzy" {
		return nil, errors.New("用户不存在")
	}

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

在这里插入图片描述

  1. go build编译

启动

  1. 启动etcd:etcd.exe
    在这里插入图片描述
  2. 启动user:user.exe -f ./etc/user.yaml
  3. 启动order:order.exe -f ./etc/order.yaml
  4. 访问url:http://localhost:8888/api/order/get/1返回:{"id":"1","name":"test order"}

goctl

goctl是go-zero微服务框架下的代码生成工具。使用 goctl 可显著提升开发效率,让开发人员将时间重点放在业务开发上,其功能有:

  1. api服务生成
  2. rpc服务生成
  3. model代码生成
  4. 模板管理

安装

go install github.com/zeromicro/go-zero/tools/goctl@latest

生成的api网关目录

.
├── etc
│   └── greet-api.yaml              // 配置文件
├── go.mod                          // mod文件
├── greet.api                       // api描述文件
├── greet.go                        // main函数入口
└── internal                        
    ├── config  
    │   └── config.go               // 配置声明type
    ├── handler                     // 路由及handler转发
    │   ├── greethandler.go
    │   └── routes.go
    ├── logic                       // 业务逻辑
    │   └── greetlogic.go
    ├── middleware                  // 中间件文件
    │   └── greetmiddleware.go
    ├── svc                         // logic所依赖的资源池
    │   └── servicecontext.go
    └── types                       // request、response的struct,根据api自动生成,不建议编辑
        └── types.go

生成的pb目录

.
├── etc
│   └── greet.yaml
├── go.mod
├── go.sum
├── greet // [1]
│   ├── greet.pb.go
│   └── greet_grpc.pb.go
├── greet.go
├── greet.proto
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   └── greetlogic.go
│   ├── server
│   │   └── streamgreeterserver.go
│   └── svc
│       └── servicecontext.go
└── streamgreeter
    └── streamgreeter.go

api语法

  • syntax语法声明
  • import语法块
  • info语法块
  • type语法块
  • service语法块
  • 隐藏通道

syntax

一个api语法文件只能有0或者1个syntax语法声明,如果没有syntax,则默认为v1版本

// api语法版本
syntax = "v1"

import语法块

import语法块可以导入拆分的api文件, 不同的api文件按照一定规则声明,可以降低阅读难度和维护难度。

import "foo.api"
import "foo/bar.api"

import(
    "bar.api"
    "foo/bar/foo.api"
)

info

info语法块是一个包含了多个键值对的语法体,其作用相当于一个api服务的描述

info(
    foo: "foo value"
    bar: "bar value"
    desc: "long long long long long long text"
)

type

在api服务中,需要用到一个结构体(类)来作为请求体,响应体的载体,因此需要声明一些结构体来完成这件事情, type语法块由golang的type演变而来,保留着一些golang type的特性,沿用golang特性有:

  1. 保留了golang内置数据类型bool,int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr ,float32,float64,complex64,complex128,string,byte,rune,
  2. 兼容golang struct风格声明
  3. 保留golang关键字
  4. 不支持time.Time数据类型,用int64表示,因为api支持客户端代码生成,并非所有客户端语言都有time.Time对应的类型
  5. 结构体名称、字段名称、不能为golang关键字
type Foo{
    Id int `path:"id"`
    Foo int `json:"foo"`
}

type Bar{
    Bar int `form:"bar"`
}

type(
    FooBar{
        FooBar int `json:"fooBar"`
    }
)

tag定义和golang中json tag语法一样,除了json tag外,go-zero还提供了另外一些tag来实现对字段的描述, 详情见下表。(tag修饰符需要在tag value后以英文逗号,隔开)

  • tag表

    绑定参数时,以下四个tag只能选择其中一个

    tag key描述提供方有效范围 示例
    jsonjson序列化taggolangrequest、responsejson:"fooo"
    path路由path,如/foo/:idgo-zerorequestpath:"id"
    form标志请求体是一个form(POST方法时)或者一个query(GET方法时/search?name=keyword)go-zerorequestform:"name"
    headerHTTP header,如 Name: valuego-zerorequestheader:"name"
  • tag修饰符

    常见参数校验描述

    tag key 描述 提供方 有效范围 示例
    optional定义当前字段为可选参数go-zerorequestjson:"name,optional"
    options定义当前字段的枚举值,多个以竖线|隔开go-zerorequestjson:"gender,options=male"
    default定义当前字段默认值go-zerorequestjson:"gender,default=male"
    range定义当前字段数值范围go-zerorequestjson:"age,range=[0:120]"

service

service语法块用于定义api服务,包含服务名称,服务metadata,中间件声明,路由,handler等。

语法:

  1. serviceSpec:包含了一个可选语法块atServer和serviceApi语法块,其遵循序列模式(编写service必须要按照顺序,否则会解析出错)

  2. atServer: 可选语法块,定义key-value结构的server metadata,‘@server’ 表示这一个server语法块的开始,其可以用于描述serviceApi或者route语法块,其用于描述不同语法块时有一些特殊关键key 需要值得注意,见 atServer关键key描述说明。

  3. serviceApi:包含了1到多个serviceRoute语法块

  4. serviceRoute:按照序列模式包含了atDoc,handler和route

  5. atDoc:可选语法块,一个路由的key-value描述,其在解析后会传递到spec.Spec结构体,如果不关心传递到spec.Spec, 推荐用单行注释替代。

  6. handler:是对路由的handler层描述,可以通过atServer指定handler key来指定handler名称, 也可以直接用atHandler语法块来定义handler名称

  7. atHandler:‘@handler’ 固定token,后接一个遵循正则[a-zA-Z][a-zA-Z-]*)的值,用于声明一个handler名称

  8. route:路由,有httpMethod、path、可选request、可选response组成,httpMethod是必须是小写。

  9. body:api请求体语法定义,必须要由()包裹的可选的ID值

  10. replyBody:api响应体语法定义,必须由()包裹的struct、array(向前兼容处理,后续可能会废弃,强烈推荐以struct包裹,不要直接用array作为响应体)

  11. kvLit: 同info key-value

  12. serviceName: 可以有多个’-'join的ID值

  13. path:api请求路径,必须以’/‘或者’/:‘开头,切不能以’/‘结尾,中间可包含ID或者多个以’-'join的ID字符串

atServer关键key:

修饰service时

key描述示例
jwt声明当前service下所有路由需要jwt鉴权,且会自动生成包含jwt逻辑的代码jwt: Auth
group声明当前service或者路由文件分组group: login
middleware声明当前service需要开启中间件middleware: AuthMiddleware
prefix添加路由分组prefix: api

修饰route时

key描述示例
handler声明一个handler-
@server(
  jwt: Auth
  group: foo
  middleware: AuthMiddleware
  prefix: api
)
service foo-api{
  @doc "foo"
  @handler foo
  post /foo/:id (Foo) returns (Bar)
}

service foo-api{
  @handler ping
  get /ping

  @doc "foo"
  @handler bar
  post /bar/:id (Foo)
}

注释

// doc
// comment

命令大全

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/488762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图论专题(各类算法和蓝桥杯真题例题)

1.图论入门 1.1存边方式 1.1.1 数组存边 1.1.2 临接矩阵存边 1.1.3 临接表存边 1.2 图的遍历和连通性 通过DFS和BFS遍历每一个图 对于非连通图,循环对每一个点dfs操作 也可以通过并查集来判断连通性 1.2.1全球变暖例题 import sys sys.setrecursionlimit(6000…

【目标检测】Haar-like特征检测简介

文章目录 一、背景模板匹配(template matching)关键点检测角点检测 二、harris特征提取原理Harris Detector 的具体流程:harris特征的可复用性旋转尺度 scale亮度 illuminationview point 三、Viola Jones检测原理Harr-like特征提取积分图训练…

QT教程demo之串口助手代码设计实现

关注WeChat Official Account 南山府嵌入式获取更多精彩 我创建了一个群关注V号后加入。因为这里不允许添加二维码 代码&#xff1a;QT_Pr 1-QT开发串口助手需要的基本文件 在QT6开发串口助手时&#xff0c;通常需要以下头文件&#xff1a; #include <QSerialPort> #i…

TCP协议策略

TCP可靠性 基于序号的确认应答(ACK)机制 TCP保证可靠性最核心的机制就是基于序号的确认应答机制。 TCP并不是百分之百可靠的&#xff0c;但是只要一条消息有应答&#xff0c;那么我们就可以确定该消息100%被对方收到了&#xff0c;这就是确认应答的意义。 可靠性不仅仅是保…

MOSS模型量化版部署过程

文章目录 项目背景配置环境与准备部署推理命令行部署报错1报错2&#xff1a; 网页版部署 项目背景 2023年4月21日&#xff0c;复旦大学自然语言处理实验室正式开放MOSS模型&#xff0c;是国内首个插件增强的开源对话大语言模型。MOSS 相关代码、数据、模型参数已在 GitHub 和 …

【键入网址到网页显示】

HTTP 对 URL 进行解析之后&#xff0c;浏览器确定了 Web 服务器和文件名&#xff0c;接下来就是根据这些信息来生成 HTTP 请求消息了。 http://www.server.com/dir1/file1.html http:访问数据的协议 www.server.com:服务器 dir1:目录名 file1.html:文件名生产 HTTP 请求信息…

SpringCloud-10_Alibaba Nacos

SpringCloud系列 SpringCloud-9、SleuthZipkin SpringCloud-8、Gateway网关服务 SpringCloud-7_OpenFeign服务调用 SpringCloud-6_Ribbon负载均衡 SpringCloud-5_模块集群化 文章目录 SpringCloud系列Nacos基础Nacos是什么&#xff1f;Nacos下载&运行 创建Nacos服务提供者…

JavaScript:哈希表

文章目录 哈希表242. 有效的字母异位词思路补充&#xff1a;JavaScript String charCodeAt() 方法代码详细分析 349. 两个数组的交集代码分析补充&#xff1a;JavaScript Set 对象思考一下哈希是什么&#xff1f;什么时候使用&#xff1f;补充&#xff1a;js 数组 map() 基本用…

github使用workflow工作流git push后自动打包部署github pages

workflows介绍 根目录新建.github/workflows/docs.yml .github/workflows/ 目录是用于存放 GitHub Actions 工作流程文件的目录&#xff0c;该目录的文件名必须以 .yml 或 .yaml 为后缀名&#xff0c;否则 GitHub 将无法识别该文件为工作流程文件。这些工作流程文件可用于自动…

速锐得基于能源油气生产智能监控的物联网应用

自2016年速锐得基于商用车国六环保排放监控管理开发以来&#xff0c;我们同时也接触了很多涉及商用车领域的深入项目&#xff0c;包括了大庆油田、山东能源、兖矿集团、陕北矿业等多家能源巨头在数字化、科技、无线远程控制、监控管理、生产效能等方面的智能化方向的趋势。 就目…

MySQL 字段为 NULL 的5大坑,大部分人踩过

数据库字段允许空值(null)的问题&#xff0c;小伙伴你遇到过吗&#xff1f; 在验证问题之前&#xff0c;我们先建一张测试表及测试数据。 构建的测试数据&#xff0c;如下图所示&#xff1a; 有了上面的表及数据之后&#xff0c;我们就来看当列中存在 NULL 值时&#xff0c;究…

基于RGB-D的6D目标检测算法

基于RGB-D的6D目标检测算法 本文参考了ITAIC的文章 A Review of 6D Object Pose Estimation 概览 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQX8ke6j-1683188966051)(https://mezereon-upic.oss-cn-shanghai.aliyuncs.com/uPic/image-20230420…

如何理解信息化、数字化和智能化的概念?一文给你解惑!

如何理解信息化、数字化和智能化的概念&#xff1f; 前两年流行“信息化”&#xff0c;网上铺天盖地都是关于“信息化”的文章&#xff0c;这两年开始流行起“数字化”&#xff0c;于是铺天盖地都是“数字化”的文章&#xff0c;最近又开始大谈“智能化”...... 但点开那些文…

常见的5种项目管理问题类型

项目管理的5大影响素&#xff1a;时间、范围、成本、风险、质量。项目经理需要对这些因素进行均衡考量&#xff0c;并根据需要略有侧重&#xff0c;进行整体把握&#xff0c;即我们常说的均衡型管理风格。而忽略任何一因素&#xff0c;都会对项目产生极大影响。 常见的项目管理…

医院导诊图怎么做?目前比较好用的医院导航地图是哪一款?

现在很多的大医院&#xff0c;不只是越建越高&#xff0c;面积也越来越大&#xff0c;同时医院内部按照门诊、住院、放射等不同功能划分的区域也是越来越多&#xff0c;走进这些“超级医院”就像走进了迷宫一样&#xff0c;如何促使病患走进医院后&#xff0c;能迅速找到要去的…

19C RAC主库 to RAC备库搭建adg报错ORA-16047(修改19C RAC DB_UNIQUE_NAME )

文章目录 前言一、问题描述二、修改DB_UNIQUE_NAME1.查看集群配置2.将hip40实例从集群中移除3.修改db_unique_name4.将hip40dg实例添加到集群资源中5.重新启动实例 三、19C RAC 密码文件替换 前言 主库环境是19C RAC备库环境也是19C RAC&#xff0c;主库到备库做adg&#xff0…

移动端动态开发能力的由来和流派

移动端动态化的由来 “动态化”并不是最近几年才产生的名词&#xff0c;而是从从互联网诞生的初期&#xff0c;这个词就已经出现了。大家所认知的早期互联网&#xff0c;其实就是各种各类的“动态网站”&#xff0c;内容数据和页面外观都不是固定的&#xff0c;都是随着服务器…

Bash脚本中的Sleep命令到底有何妙用?

在编写Bash脚本时&#xff0c;有时需要在程序执行过程中加入一些等待时间&#xff0c;例如等待某个操作完成或等待某个进程退出。此时可以使用sleep命令来实现。 sleep命令可以让脚本暂停执行一段时间&#xff0c;其基本语法为&#xff1a; sleep <seconds>其中&#xf…

细数【SD-WEBUI】的模型:谁是最适合的模型从哪里找到它们

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;基础模型&#xff08;Stable-Diffusion模型&#xff09;&#xff08;1.1&#xff09;ChilloutMix&#xff08;仿真&#xff09;&#xff08;1.2&#xff09;BasilMix&#xff08;仿真&#xff09;&#xff0…

如何使用 Linux Cron Job 优化WP-Cron以获得更好的性能

在本教程中&#xff0c;我将向您展示如何通过在 Linux 上用 Crontab 替换默认的 WP-Cron 触发机制来优化 WordPress 性能。 WordPress 使用 WP-Cron 来运行计划任务&#xff0c;许多用户已经在使用。 但它的工作方式并不理想。 在每次页面加载时&#xff0c;WP-Cron 检查计划…