当前位置: 首页 > news >正文

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

文章目录

      • 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 mainimport ("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 mainimport ("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 stringid, _ = 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.Bootstrapif 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 signalif err := app.Run(); err != nil {panic(err)}
}

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

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

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

相关文章:

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

文章目录 1.Kratos 简介2.传输协议3.日志4.错误处理5.配置管理6.wire 1.Kratos 简介 Kratos并不绑定于特定的基础设施,不限定于某种注册中心,或数据库ORM等,所以您可以十分轻松地将任意库集成进项目里,与Kratos共同运作。 API -&…...

首个实时 AI 视频生成技术发布;科大讯飞发布星火大模型 4.0 丨 RTE 开发者日报

开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…...

什么是容器镜像

什么是容器镜像? 1. 容器镜像的两个重要原则 容器镜像是容器化应用程序的基础,它包含了运行应用程序所需的一切——代码、运行时、库和依赖项。理解容器镜像的两个重要原则非常重要: 不可变性:容器镜像一旦构建,就不…...

ElasticSearch-Windows系统ElasticSearch(ES)的下载及安装

前言 下载ElasticSearch 可以进入ElasticSearch官方下载地址,选择与电脑系统相对应的版本;博主已经上传资源,或者点此直接免费下载,本次演示版本为8.14.1。 注意: Elasticsearch 5 需要 Java 8 以上版本;…...

【应用开发二】GPIO操控(输出、输入、中断)

1 操控GPIO方式 控制目录:/sys/class/gpio /sys/class/gpio目录下文件如下图所示: 1.1 gpiochipX目录 功能:当前SoC所包含的所有GPIO控制器 i.mx6ull一共包含5个GPIO控制器,分别为GPIO1~5分别对应gpiochip0、gpiochip32、gpi…...

单点登录方法

一、父域cookie:两个有相同父域名的二级域名之间可以跨域传递cookie //注意该接口的地址也是baidu.com下属的二级域名:a.baidu.com //全部接口地址为:a.baidu.com/dev-api/system/ecdWeb/login。如果不是a.baidu.com那么根本带不过去 //其实可以理解为通过该方法将cookie传给…...

springboot集成JPA并配置hikariCP连接池问题解决

一、引入需要的依赖 springboot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/></parent> jpa依赖 <!--…...

vue2的双向绑定

vue是一个mvvm框架&#xff0c;即数据双向绑定&#xff0c;即当数据发生变化的时候&#xff0c;视图也就发生变化&#xff0c;当视图发生变化的时候&#xff0c;数据也会跟着同步变化。 Vue.js 2 中的双向绑定是通过 v-model 指令实现的。v-model 指令可以在表单输入元素上创建…...

Vue3 国际化i18n

国际化i18n方案 1. 什么是i18n2. i18n安装、配置及使用2.1 安装2.2 配置2.3 挂载到实例2.4 组件中使用2.5 语言切换 1. 什么是i18n i18n 是“国际化”的简称。在资讯领域&#xff0c;国际化(i18n)指让产品&#xff08;出版物&#xff0c;软件&#xff0c;硬件等&#xff09;无…...

算法金 | 使用随机森林获取特征重要性

大侠幸会幸会&#xff0c;我是日更万日 算法金&#xff1b;0 基础跨行转算法&#xff0c;国内外多个算法比赛 Top&#xff1b;放弃 BAT Offer&#xff0c;成功上岸 AI 研究院 Leader&#xff1b; <随机森林及其应用领域> 随机森林是一种强大的机器学习算法&#xff0c;其…...

网络安全的重要性

网络安全的重要性 网络安全是指保护网络系统免受未授权的访问、攻击、破坏或未经授权的数据泄露的能力。随着互联网的普及和数字化进程的加速&#xff0c;网络安全问题日益凸显&#xff0c;成为个人、企业和国家必须面对的重要挑战。 网络安全的威胁 网络安全威胁包括黑客攻…...

Leetcode40 无重复组合之和

题目描述&#xff1a; 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 思路分析 这个题是…...

详解MATLAB中处理日期和时间的函数

在MATLAB中处理日期和时间时&#xff0c;可以使用多种函数来进行计时和时间差计算。以下是对一些常用函数的详细解释&#xff1a; 1. tic 和 toc 用途&#xff1a;用来测量一段代码执行的时间。用法&#xff1a;tic; % 启动秒表 % 你的代码 elapsedTime toc; % 停止秒表&…...

Java养老护理助浴陪诊小程序APP源码

&#x1f496;护理助浴陪诊小程序&#x1f496; 一、引言&#xff1a;养老新趋势&#x1f331; 在快节奏的现代生活中&#xff0c;养老问题逐渐成为了社会关注的焦点。如何为老年人提供便捷、贴心的服务&#xff0c;让他们晚年生活更加安心、舒适&#xff0c;是我们每个人都需…...

go的singleFlight学习

Package singleflight provides a duplicate function call suppression mechanism “golang.org/x/sync/singleflight” 原来底层是 waitGroup&#xff0c;我还以为等待的协程主动让出 cpu 了&#xff0c;没想到 waitGroup.Wait() 阻塞了 doCall 不但返回值是 func 的 val 和…...

高电压技术-冲击高压发生器MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 冲击电压发生器是产生冲击电压波的装置&#xff0c;用于检验电力设备耐受大气过电压和操作过电压的绝缘性能&#xff0c;冲击电压发生器能产生标准雷电冲击电压波形&#xff0c;雷电冲击电压截波,标准操作冲击…...

【STM32】SysTick系统滴答定时器

1.SysTick简介 CM4内核的处理和CM3一样&#xff0c;内部都包含了一个SysTick定时器&#xff0c;SysTick 是一个24 位的倒计数定时器&#xff0c;当计到0 时 &#xff0c;将 从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除&#xf…...

编码遵循五大设计原则创建出更加健壮、可维护和可扩展的软件系统

一、单一职责原则&#xff08;SRP&#xff09; * 定义&#xff1a;一个类应该只有一个引起它变化的原因。 * 解释&#xff1a;意味着一个类应该专注于做一件事情&#xff0c;当需求发生变化时&#xff0c;只影响到一个类。这有助于降低类间的耦合&#xff0c;使得代码更易于理…...

记录一个问题

问题描述 如果一个物料既在A总成零件号下计算为托盘库&#xff0c;在B总成零件号下计算为箱库&#xff0c;则放于箱库。 A中选择排名第21的递补进托盘库。&#xff08;也需要判断递补的是否在其他总成零件中为箱库&#xff0c;是的话继续递补判断&#xff09; 解决思路 为了…...

ONLYOFFICE 8.1版本桌面编辑器测评:重塑办公效率的巅峰之作

在数字化办公日益普及的今天&#xff0c;一款高效、便捷且功能强大的桌面编辑器成为了职场人士不可或缺的工具。ONLYOFFICE 8.1版本桌面编辑器凭借其卓越的性能和丰富的功能&#xff0c;成功吸引了众多用户的目光。今天&#xff0c;我们将对ONLYOFFICE 8.1版本桌面编辑器进行全…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...