[Go Web] Kratos 使用的简单总结

news2024/11/27 10:27:00

文章目录

      • 1.Kratos 简介
      • 2.传输协议
      • 3.日志
      • 4.错误处理
      • 5.配置管理
      • 6.wire

1.Kratos 简介

Kratos并不绑定于特定的基础设施,不限定于某种注册中心,或数据库ORM等,所以您可以十分轻松地将任意库集成进项目里,与Kratos共同运作。

在这里插入图片描述
API -> Service(wire) -> DB

  1. 可以看到kratos将整个服务大体分为了3层,API / Service / DB。
  2. 左侧标注了在 Service和DB层,使用依赖注入(DI)进行实现,工具名称为Wire。
  3. 可以看到Wire这个工具几乎贯穿Kratos架构始终,是一个大角色。

2.传输协议

支持http + grpc两种调用方式,通过编写proto文件来实现。

一般,http开放给外部调用,可以使用restful风格定义。grpc面向内部微服务之间进行调用。

在这里插入图片描述

​ 在项目中,会以这样的结构出现,并且可以对不同协议进来的请求进行处理,添加处理的中间件,如权限校验、熔断限流等等。

3.日志

在kratos中,可以自定义日志框架选型,设置日志格式和输出内容,然后将logger对象以依赖注入的方式,分配给server中的grpc server和http server,这样就可以实现每次收到请求后的日志打印。

将logger对象以依赖注入的方式,注入到业务层,就可以在业务层中统一使用logger进行输出。

4.错误处理

在grpc中,比较通用的一种错误处理方式就是直接通过 proto 预定义定义错误码,然后通过 proto-gen-go 生成帮助代码,直接返回 error。

{
    // 错误码,跟 http-status 一致,并且在 grpc 中可以转换成 grpc-status
    "code": 500,
    // 错误原因,定义为业务判定错误码
    "reason": "USER_NOT_FOUND",
    // 错误信息,为用户可读的信息,可作为用户提示内容
    "message": "invalid argument error",
    // 错误元信息,为错误添加附加可扩展信息
    "metadata": {
      "foo": "bar"
    }
}

这里可以发现,为了兼容grpc,在http的返回结果中,code也无法自定义,只能跟随httpcode。所以这里客户端或者第三方去处理错误时,需要判断reason字段。

5.配置管理

使用proto文件定义配置和生成struct,然后将yaml中的内容读取到对应struct 字段中进行使用。

在这里我们可以注意到,在kratos中,除了传输格式使用了proto进行定义之外,错误处理和配置管理,也使用了proto来进行。可以说,一切皆proto。

6.wire

Wire 是一个灵活的依赖注入工具(需要安装),通过自动生成代码的方式在编译期完成依赖注入。通过 Wire 进行初始化代码,可以很好地解决组件之间的耦合,以及提高代码维护性。

打开Kratos的示例项目,从main入口看,有一处调用了wireApp方法,这里就是一切的源头(万恶之源)。

这个方法调用的是main同目录的wire文件中的wireApp方法,同目录的wire_gen.go实现了此方法。

wire_gen中去实例化不同service和组建的对象,用于调用。关系图如下:

在这里插入图片描述

在这里插入图片描述

server -> service -> biz -> data

main.go -> wire.go(wire_gen.go)

在这里插入图片描述

wire.go 中有用到ProviderSet

package main

import (
	"kratos-demo03/internal/biz"
	"kratos-demo03/internal/conf"
	"kratos-demo03/internal/data"
	"kratos-demo03/internal/server"
	"kratos-demo03/internal/service"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/google/wire"
)

// wireApp init kratos application.
func wireApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, func(), error) {
	panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))
}

main.go 有用到App和Config

package main

import (
	"flag"
	"os"

	"kratos-demo03/internal/conf"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/config/file"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"

	_ "go.uber.org/automaxprocs"
)

// go build -ldflags "-X main.Version=x.y.z"
var (
	// Name is the name of the compiled software.
	Name string
	// Version is the version of the compiled software.
	Version string
	// flagconf is the config flag.
	flagconf string

	id, _ = os.Hostname()
)

func init() {
	flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml")
}

func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server) *kratos.App {
	return kratos.New(
		kratos.ID(id),
		kratos.Name(Name),
		kratos.Version(Version),
		kratos.Metadata(map[string]string{}),
		kratos.Logger(logger),
		kratos.Server(
			gs,
			hs,
		),
	)
}

func main() {
	flag.Parse()
	logger := log.With(log.NewStdLogger(os.Stdout),
		"ts", log.DefaultTimestamp,
		"caller", log.DefaultCaller,
		"service.id", id,
		"service.name", Name,
		"service.version", Version,
		"trace.id", tracing.TraceID(),
		"span.id", tracing.SpanID(),
	)
	c := config.New(
		config.WithSource(
			file.NewSource(flagconf),
		),
	)
	defer c.Close()

	if err := c.Load(); err != nil {
		panic(err)
	}

	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}

	app, cleanup, err := wireApp(bc.Server, bc.Data, logger)
	if err != nil {
		panic(err)
	}
	defer cleanup()

	// start and wait for stop signal
	if err := app.Run(); err != nil {
		panic(err)
	}
}

在每个模块中,只需要一个 ProviderSet 提供者集合,就可以在 wire 中进行依赖注入。

有一个数据库连接对象,service需要操作数据库,依赖数据库连接对象。这时候我们可以声明数据库连接对象在ProviderSet集合,然后在service对象处声明,我需要一个数据库连接对象。 然后我们使用wire工具,就可以自动帮我们生成依赖注入的代码。

这里的依赖注入让代码间的依赖关系一目了然。只需要查看wire_gen.go代码就可以了解依赖关系。

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

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

相关文章

算法基础-----【递归回溯】

1、递归 递归是一种算法结构,递归会出现在子程序中自己调用自己或间接地自己调用自己。递归就是分为递去和归来。 递去:递归的问题必须可以分解为若干规模较小,与原问题相同的子问题,这些子问题可以用相同的解题思路解决。 归来…

【Python】已解决:FileNotFoundError: [Errno 2] No such file or directory: ‘配置信息.csv‘

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决:FileNotFoundError: [Errno 2] No such file or directory: ‘配置信息.csv’ 一、分析问题背景 在编写Python代码进行文件操作时,开发者可能会遇到…

【嵌入式DIY实例】-LCD ST7735显示LM35传感器数据

LCD ST7735显示LM35传感器数据 文章目录 LCD ST7735显示LM35传感器数据1、硬件准备与接线2、代码实现本文将介绍如何使用 LM35 模拟温度传感器构建一个简单的温度计,其中温度值打印在 ST7735 TFT 显示屏上(以摄氏度、开尔文度和华氏度为单位)。 ST7735 TFT是一款分辨率为128…

大数据组件--Hue

Apache Hue hue是一个集成化的大数据可视化软件,可以通过hue访问浏览操作主流的大数据生态圈软件。hue本身来自于cloudera后来贡献给了apachehue本身是一个web项目,基于python实现的,通过该web项目的UI集成了各个软件的UI 下面是一个hue调度…

CUDA 编程

## blocksize和gridsize设置 使用deviceQuery查看GPU相关信息(下图为1080 ti)blocksize的最大值建议不要超过Maximum number of threads per block(1024)由于每个block里的线程需要被分为数个wrap,而wrap size为32(Warp size&…

加密与安全_Java 加密体系 (JCA) 和 常用的开源密码库

文章目录 Java Cryptography Architecture (JCA)开源国密库国密算法对称加密(DES/AES⇒SM4)非对称加密(RSA/ECC⇒SM2)散列(摘要/哈希)算法(MD5/SHA⇒SM3) 在线生成公钥私钥对,RSA公私钥生成参考…

BGP中的TCP连接源地址问题

3.TCP连接源地址(用loop back地址是最优选择) 应用场景与理论: 由于BGP应用于大型网络中,为了避免单点失败,往往需要通过多条链路连接,当一条链路故障时候就用另一条链路继续工作,但是BGP又无法…

Navicat安装与连接教程

navicat 的安装 官网:https://www.navicat.com.cn/ 进入官网之后点击左上角的产品,然后往下滑动就可以看见许多类型,我们使用的是MongoDB数据库,所以就下载Navicat 17 for MongoDB 进入到这里之后,选择自己的系统版本…

llm-universe | 三. 搭建知识库

搭建知识库 一. 词向量和向量知识库1. 词向量1.词向量概念2.词向量优势3. 一般构建词向量的方法 2.向量数据库 二. 使用Embedding API三. 数据处理一.读取文档1. PDF 文档2.MD 文档 二.数据清洗三.文档分割 四.搭建并使用向量数据库一.前序工作二. 构建Chroma向量库三、向量检索…

农业新质生产力数据(2012-2022年)原始+dofile+测算数据集

数据简介:农业新质生产力是指在现代农业发展中,通过融合尖端科技、信息技术与创新管理模式,实现农业生产效率飞跃、产品质量显著提升及生产可持续性增强的一种革新性生产能力,农业新质生产力代表了从依赖传统资源转向依靠科技创新…

ctfshow web入门 sqli-labs web517--web524

web517 注入点id ?id-1’union select 1,2,3– 确认是否能够注入 ?id-1union select 1,database(),3-- 爆出库名 security爆出表名 ?id-1union select 1,(select group_concat(table_name) from information_schema.tables where table_schemasecurity),3-- emails,refer…

在WSL Ubuntu中启用root用户的SSH服务

在 Ubuntu 中,默认情况下 root 用户是禁用 SSH 登录的,这是为了增加系统安全性。 一、修改配置 找到 PermitRootLogin 行:在文件中找到 PermitRootLogin 配置项。默认情况下,它通常被设置为 PermitRootLogin prohibit-password 或…

【papaparse插件】前端预览csv文件

需求:就是可以在前端直接预览csv文件的内容 1.了解csv文件 1.1 csv文件和xlsx、xls文件的异同 首先了解一下csv文件和excel文件(xlsx,xls)有什么异同,简单来说他们都是存储表格数据的文件,csv只能显示较…

怎样规避液氮容器内部结霜的问题

液氮容器内部结霜问题一直是我们在使用液氮储存罐时遇到的一个棘手难题。液氮的极低温度使得容器内部很容易产生结霜现象,这不仅影响了容器的正常使用,还可能对内部样品或设备造成损坏。因此,如何有效规避液氮容器内部结霜问题成为了每个使用…

软件工程实验

实验环境和需求 用户可以对相片进行按类别管理,用户可以设定不同的类别,然后上传照片到相应的类别中,并能进行照片的删除,注释 运行 运行并访问 localhost 8090,图片在数据库中的信息是D:/upgrade 后面的内容 se…

FCN/UNET/deeplabv3 语义分割 标注 重叠/重复/覆盖 的处理方案,以及自定义覆盖优先级

在对FCN/UNET/deeplabv3等语义分割时,标准的要求是对每一个像素点分开标记,即不允许出现重叠覆盖的情形:如下图所示 但不可避免的人工标注时会出现一定的标注重叠/重复/覆盖甚至有的时候需要标注就是重复的,例如需要识别面板上赃物的情形,标记了面板和脏污,标注是重叠的,但是实…

陶瓷化聚烯烃研究逐渐增多 行业即将进入规模化生产阶段

陶瓷化聚烯烃研究逐渐增多 行业即将进入规模化生产阶段 陶瓷化聚烯烃是一种陶瓷化高分子材料,同时也是一种防火阻燃复合材料,主要由聚烯烃(作为基材)、成瓷填料(如无机硅酸盐等)、助熔剂、补强剂&#xff0…

【安全开发】内网扫描器

文章目录 前言现实现的功能较少后序开发会逐步加入简单漏洞探探测和代理功能。 一、开发过程1.项目结构2.main.go3.core模块3.1 scanner.go3.2 service.go 4.bruteforc4.1 bruteforce.go 二、使用步骤 前言 为什么要写这个? fscna被杀的概率太高(哪天二…

JS(JavaScript)事件处理(事件绑定)趣味案例

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

c语言--指针

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…