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

go-zero 实战(5)

引入Prometheus

用 Prometheus 监控应用

1. 用 docker 启动 Prometheus

编辑配置位置,我将 prometheus.yaml 和 targets.json 文件放在了 /opt/prometheus/conf目录下

prometheus.yaml

global:scrape_interval: 15s # 抓取间隔evaluation_interval: 15s # 评估间隔scrape_configs:- job_name: 'file_ds'file_sd_configs:- files:- 'targets.json'

由于 prometheus.yaml 文件中,用到了 targets.json 文件,因此,引入 targets.json文件

targets.json

[{"targets":["192.168.10.20:9081"],"labels": {"job": "user-api","app": "user-api","env": "test","instance": "192.168.10.20:8888"}    }
]

我的应用是启动在 宿主机的 8888 端口,因此,我这里写了宿主机的 ip 和端口。
上面的 9081 端口,可以随便写。但是要与应用中的配置一致,看后面配置。

docker run -d --name prometheus --dns=192.168.10.20 -p 9090:9090  -v /opt/prometheus/conf/prometheus.yaml:/etc/prometheus/prometheus.yml  -v /opt/prometheus/conf/targets.json:/etc/prometheus/targets.json quay.io/prometheus/prometheusdocker run -d --name prometheus --network host   -v /opt/prometheus/conf/prometheus.yaml:/etc/prometheus/prometheus.yml  -v /opt/prometheus/conf/targets.json:/etc/prometheus/targets.json quay.io/prometheus/prometheus

下面两条命令都可以启动 Prometheus。

2. 启动应用

修改应用的配置文件 userapi/etc/userapi-api.yaml 文件。

在这里插入图片描述
增加了 Prometheus 配置,端口号与 targets.json 文件中的 targets 条目标识的端口号保持一致。

3.测试

访问 http://192.168.10.20:9090/targets?search=
在这里插入图片描述
这样可以看到 Prometheus 监控了应用。

引入 jaeger

jaeger 是一个用于链路追踪的中间件。

1. docker 启动 jaeger

docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778  -p 16686:16686 -p 14268:14268  -p 14269:14269   -p 9411:9411 jaegertracing/all-in-one:latest

这样启动的 jaeger,数据默认是放在内存中的。可以根据直接的需求,选择将数据放在 elasticsearch或其它存储中。

  • 其中 16686 是 ui 端口,直接访问 http://localhost:16686 便可以进入到 ui 界面
    在这里插入图片描述

2. 修改 userapi/etc/userapi-api.yaml 文件

在配置文件中加入如下配置:

Telemetry:Name: user-apiEndpoint: http://localhost:14268/api/tracesSampler: 1.0Batcher: jaeger

3. 测试

启动 userapi 应用,用postman 访问接口。
在这里插入图片描述
这样就可以在 jaeger 的 ui 上看到访问的接口。

分布式事务

分布式事务也是微服务架构中必不可少的一部分。go-zero 使用了dtm的方案来解决分布式事务问题。

1. 引入 DTM

官网链接

1. github clone 项目

项目地址:https://github.com/dtm-labs/dtm.git

2. 进入项目

创建 conf.yml 配置文件,加入如下配置:

MicroService: # gRPC/HTTP based microservice configDriver: 'dtm-driver-gozero' # name of the driver to handle register/discoverTarget: 'etcd://localhost:2379/dtmservice' # register dtm server to this urlEndPoint: 'localhost:36790'

3. 启动dtm

从源码处启动 dtm

go run main.go -c conf.yml 

在这里插入图片描述

2. 创建表

在当前使用的微服务对应的数据中创建表。我们曾在 go-zero实战(2)中创建过zero-mall数据库。同样在该数据库创建 barrier表。

create table if not exists barrier(id bigint(22) primary key auto_increment,trans_type varchar(45),gid varchar(128),branch_id varchar(128),op varchar(45),barrier_id varchar(45),reason varchar(45),create_time datetime default now(),update_time datetime default now(),key(create_time),key(update_time),unique key(gid, branch_id, op, barrier_id)
);

3. 创建积分服务

1. 在 zero_mall 数据库中 创建 user_score 表

create table user_score(id bigint(0) not null auto_increment,user_id bigint(0) not null,score int(0) not null,primary key(id) using btree
);

2. 创建 user_score.proto 文件

syntax = "proto3";package userscore;option go_package = "./score";message UserScoreRequest {int64 userId = 1;int32 score = 2;
}message UserScoreResponse {int64 userId = 1;int32 score = 2;
}service UserScore {rpc saveScore(UserScoreRequest) returns(UserScoreResponse);rpc saveScoreCallback(UserScoreRequest) returns(UserScoreResponse);
}

为了使用 dmt 实现的分布式事务,saveScore 方法,需要有一个相应的 Callback 方法。为了在发生异常回滚时,执行该方法。

3. 生成代码

goctl rpc protoc user_score.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.

4. 整理代码

  1. 将 生成的 user_score.pb.go 文件和 user_score_grpc.pb.go 文件放入 rpc-common 工程的score目录下。
  2. 将 userscore.go 文件放入 rpc-common 工程的 userscore 目录下。
  3. 在user-score 创建 go.mod 文件,如下:
    module user-scorego 1.22.2
    
  4. 在 mall 工程下,执行如下命令:
    go work use user-score  # 加入 workspace
    go mod tidy             # 下载依赖
    
  5. 在 user-score 创建 database 目录,并增加 sqlx.go 文件,参考 go-zero 实战(3)
  6. 将user 微服务 user/internal 目录下的 dao、repo、model三个目录复制一份到 user-score 微服务的 user-score/internal 目录下并做相应的命名修改。
  7. 修改 user-score/etc/userscore.yaml 文件
    Name: score.rpc
    ListenOn: 127.0.0.1:8081
    Etcd:Hosts:- 127.0.0.1:2379Key: score.rpc
    Mysql:Datasource: root:thinker@tcp(127.0.0.1:3306)/zero_mall?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghaiCacheRedis:- Host: 127.0.0.1:6379Pass: thinkerType: node
    
  8. 修改 user-score/internal/svc/servicecontext.go 文件,加入 UserScoreRepo
  9. 修改生成的 savescorelogic.go 和 savescorecallbacklogic.go 文件

到此,积分服务创建完成。

4. 在 userapi 中调用积分服务

1. 修改 userapi/etc/userapi-api.yaml 文件

加入 user-score 微服务的 rpc 配置

UserScoreRpc:Etcd:Hosts:- 127.0.0.1:2379Key: score.rpc

2. 修改 userapi/intrenal/config/config.go 文件

在这里加入 user-score 微服务的 rpc。
在这里插入图片描述

3. 在 userapi/internal/svc/servicecontext.go 文件为上一步增加的变量赋值

在这里插入图片描述

因为userapi 是作为 rpc 客户端,而 user-score 微服务是 rpc 服务端。并且这两个服务都会用到公共的部分,于是,将公共部分抽取到 rpc-common 下。这样,userapi 微服务不会用到 user-score 微服务下的代码。

4. 修改 userapi/internal/logic/userapilogic.go 文件

我们修改了 Register 接口,增加调用 user-score 微服务的代码。

到此,算是正常走通了。在 userapi 微服务下,注册功能实现时,同时调用了 user服务和 user-score 服务。

5. 测试

在这里插入图片描述

代码,这部分代码提交到了 score 分支。

6. 使用 DTM

在上面的注册功能里,从userapi 远程调用了 user 和 user-score 两个服务。试想,如果有一个微服务调用错误,显然不会影响到另一个。我们引入分布式事务,就为了解决在注册成功后,用户能够增加积分。如果积分增加失败的情况下,也要保证注册不成功。

1. 在项目中导入 dtm

分别在 /mall/userapi、/mall/user、/mall/user-score 下执行命令:

go get github.com/dtm-labs/dtm

2. 项目中加入dtm 驱动

  1. 修改 userapi/internal/logic/userapilogic.go 文件
    加入驱动

    	_ "github.com/dtm-labs/dtmdriver-gozero"// 这里的地址在文章 分布式事务 1.2 这个步骤,修改配置文件时候,指定的地址// 先上看 1.2 步骤可以找到var dtmServer = "etcd://localhost:2379/dtmservice" 
    

3. 修改 userapi/internal/userapilogic.go 文件

修改 Register 方法的逻辑,引入 dtm

func (l *UserLogic) Register(req *types.Request) (resp *types.Response, err error) {gid := dtmgrpc.MustGenGid(dtmServer)sagaGrpc := dtmgrpc.NewSagaGrpc(dtmServer, gid)userServer, err := l.svcCtx.Config.UserRpc.BuildTarget()if err != nil {return nil, err}userScoreServer, err := l.svcCtx.Config.UserScoreRpc.BuildTarget()if err != nil {return nil, err}userReq := &user.UserRequest{Id:     req.Id,Name:   req.Name,Gender: req.Gender,}// call save methodsagaGrpc.Add(userServer+"/user.User/save", userServer+"/user.User/saveCallback", userReq)// 这个地方,应该是传入一个User,因为远程调用拿不到返回值。暂且先写死,为了测试效果。userScoreReq := &score.UserScoreRequest{UserId: req.Id,Score:  10,}sagaGrpc.Add(userScoreServer+"/userscore.UserScore/saveScore", userScoreServer+"/userscore.UserScore/saveScoreCallback", userScoreReq)sagaGrpc.WaitResult = trueerr = sagaGrpc.Submit()if err != nil {fmt.Println("---------------------------")fmt.Println(err)return nil, err}//fmt.Sprintf("register add score %d \n", userScore.Score)return &types.Response{Message: "success",Data:    "",}, nil
}

核心代码,就是将原来直接的rpc 调用,委托给 dtm 调用。

4. 修改服务端

  1. 修改 user-score/internal/logic/savescorelogic.go 文件
    引入 dtm
  2. 修改 user/internal/logic/userlogic.go 文件

5. 测试

在这里插入图片描述

指定id,插入用于,测试成功。

6. 测试事务

现在模拟 user-score 服务的逻辑出现了问题。检查事务是否生效。

在这里插入图片描述
我们用 postman测试后,发现, user 表中插入了新的数据,但是积分表中是没有新数据的。那是否事务没有生效呢?
在这里插入图片描述
当从后台打印的日志可以看出,saveCallback 方法被调用。

这里需要明白一点。

userapi/internal/logic/userapilogic.go 代码逻辑如下:

在这里插入图片描述
代码提交到了 dtm 分支。代码

相关文章:

go-zero 实战(5)

引入Prometheus 用 Prometheus 监控应用 1. 用 docker 启动 Prometheus 编辑配置位置,我将 prometheus.yaml 和 targets.json 文件放在了 /opt/prometheus/conf目录下 prometheus.yaml global:scrape_interval: 15s # 抓取间隔evaluation_interval: 15s # 评估…...

Python异常处理:打造你的代码防弹衣!

Hi,我是阿佑,上文咱们讲到——揭秘Python的魔法:装饰器的超能力大揭秘 ‍♂️✨,阿佑将带领大家通过精准捕获异常、使用with语句和上下文管理器、以及异常链等高级技巧来增强代码的健壮性。就像为代码穿上防弹衣,保护它…...

Linux——进程与线程

进程与线程 前言一、Linux线程概念线程的优点线程的缺点线程异常线程用途 二、Linux进程VS线程进程和线程 三、Linux线程控制创建线程线程ID及进程地址空间布局线程终止线程等待分离线程 四、习题巩固请简述什么是LWP请简述LWP与pthread_create创建的线程之间的关系简述轻量级进…...

ping 探测网段哪些地址被用

#!/bin/bash# 遍历192.168.3.1到192.168.3.254 for i in {1..254} doip"192.168.3.$i"# 对每个IP地址进行三次ping操作if ping -c 3 -W 1 $ip > /dev/null 2>&1thenecho "$ip: yes"fi done$ sh test.sh 192.168.3.1: yes 192.168.3.95: yes 192.…...

OSPF问题

.ospf 选路 域内 --- 1类,2类LSA 域间 --- 3类LSA 域外 --- 5类,7类LSA --- 根据开销值的计算规则不同,还分为类型1和类型2 ospf 防环机制 区域内防环:在同一OSPF区域内,所有路由器通过交换链路状态通告&#xff…...

asgasgas

asdgasdgsa...

Go语言实现人脸检测(Go的OpenCV绑定库)

文章目录 OpenCVGithub官网安装环境变量 Go的OpenCV绑定库Github文档安装搜索视频设备ID显示视频检测人脸 OpenCV Github https://github.com/opencv/opencv/ 官网 https://opencv.org/ 安装 brew install opencv brew upgrade opencv安装目录 cd /usr/local/opt/opencv…...

springboot中线程池的使用

一、概念 线程池就是将多个线程对象放入一个池子里面,例如一个池塘,线程池就是这个池塘,池塘里面的鱼就是线程池中的多个线程对象。1. 每一个线程,在一段时间内只能执行一个任务。2. 线程池中的各个线程是可以重复使用的。 二、创…...

ubuntu20.04 开机自动挂载外加硬盘

文章目录 一、问题描述二、操作1. 查找新添盘符2. 格式化硬盘文件系统3. 挂载硬盘4. 开机自动挂载5. 取消挂载6. 查看挂载的硬盘信息 一、问题描述 因电脑使用一段时间后自身硬盘不足,需外加硬盘使得电脑自动识别加载。 二、操作 1. 查找新添盘符 sudo blkid自己…...

5.18 TCP机械臂模拟

#include <netinet/tcp.h>//包含TCP选项的头文件 #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/input.h>//读取输入事件 #include <sys/types.h> #include <sys/stat.h&…...

linux---线程控制

线程和进程 以前我们要同时跑多个程序&#xff0c;可以通过fork()多个子进程&#xff0c;然后通过系统函数进行程序的替换&#xff0c;但是创建进程代价大&#xff0c;不仅要拷贝一份父进程的地址空间&#xff0c;页表&#xff0c;文件表述符表等。但是线程不需要因为是进程的…...

低代码开发:拖拽式可视化构建工业物联网系统

什么是低代码&#xff1f; 低代码(Low Code)是一种可视化的软件开发方法&#xff0c;通过最少的手动编码可以更快地交付应用程序。低代码平台的图形用户界面和拖放功能可自动执行开发过程的各个方面&#xff0c;从而消除对传统计算机编程方法的依赖。 什么是低代码平台&#…...

【撸源码】【ThreadPoolExecutor】线程池的工作原理深度解析——上篇

1. 前言 线程池这块&#xff0c;作为高频面试题&#xff0c;并且实际使用场景巨多&#xff0c;所以出了这篇文章&#xff0c;一块来研究一下线程池的实现原理&#xff0c;运行机制&#xff0c;从底层深挖&#xff0c;不再局限于面试题。 2. 线程池概览 2.1. 构造器 线程池总…...

webpack 学习之 五大核心

为什么用 webpack webpack 官网传送门 … 官网&#xff1a;webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。将你项目中所需的每一个模块组合成一个或多个 bundles&#xff0c;它们均为静态资源&#xff0c;用于展示你的内容。总结&#xff1a;汇总所有模块…...

Android逆向抓包技巧 - Hook 底层通信

一,请求的本质 平时开发使用的 http 或 https 均属于应用层的协议,其本质都会调用 TCP 发送请求。 例如:你在 Python 中使用 requests 模块发送一个 http 请求,其底层就是使用 socket 模块 + TCP 实现发送的请求。 import requestsres = requests.get("http://wiki…...

深入解析力扣162题:寻找峰值(线性扫描与二分查找详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…...

模板方法及设计模式——Java笔记

模板方法及设计模式 抽象类体现的就是一种模板模式的设计&#xff0c;抽象类作为多个子类的通用模板&#xff0c;子类在抽象类的基础上进行扩展、改造&#xff0c;但子类总体上会保留抽象类的行为方式。 解决的问题&#xff1a; 当功能内部一部分实现是确定的&#xff0c;另一…...

K8S认证|CKA题库+答案| 11. 创建PVC

11、创建PVC 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node ok8s master …...

多微信如何高效管理?一台电脑就能搞定!

对于有多个微信号的人来说&#xff0c;管理这些微信无疑是一道难题。 今天&#xff0c;就给大家分享一个能够让你高效管理多个微信号的神器——个微管理系统&#xff0c;下面&#xff0c;就一起来看看它都有哪些功能吧&#xff01; 1、多号同时登录在线 系统支持多个微信号同…...

安装harbor出现问题: Running 1/1 ✘ Network harbor_harbor Error

安装harbor出现问题&#xff1a; [] Running 1/1 ✘ Network harbor_harbor Error 0.2s failed to create network harbor_harbor: Error response from daemon: Fa…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...