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

Hertz+Kitex快速上手开发

本篇文章以用户注册接口为例,快速上手Hertz+Kitex

以用户注册接口来演示hertz结合kitex实现网关+微服务架构的最简易版本

项目结构

api- gateway:网关实现,这里采用hertz框架

idl:接口定义用来生成kitex代码

kitex_gen:thrift协议自动生成的代码

rpc_service:微服务的服务逻辑

hertz框架

hertz框架其实和gin作用差不多,为字节跳动开源的go语言web网络框架

框架细节部分 大家感兴趣可以参考官方文档路由 | CloudWeGo

快速引入

服务逻辑

用户请求注册接口->网关层服务拿到进行处理路由,分发到具体的微服务

核心处理路由函数handler.go
package userimport ("context""log""time""video_douyin/kitex_gen/user"             // Kitex生成的用户服务数据结构"video_douyin/kitex_gen/user/userservice" // Kitex生成的用户服务客户端"github.com/cloudwego/hertz/pkg/app"        // Hertz HTTP上下文处理"github.com/cloudwego/kitex/client"         // Kitex客户端核心"github.com/cloudwego/kitex/client/callopt" // Kitex调用选项
)// 全局用户服务客户端实例
var userClient userservice.Client// 初始化Kitex客户端连接
func init() {c, err := userservice.NewClient("douyin.video.user",                  // 服务名client.WithHostPorts("0.0.0.0:8888"), // 服务地址)if err != nil {panic(err) // 连接失败终止程序}userClient = c
}// Handler 处理用户注册HTTP请求
func Handler(ctx context.Context, c *app.RequestContext) {req := user.NewRegisterRequest()   // 创建注册请求结构体log.Printf("Phone: %s", req.Phone) // 记录请求参数// 调用用户服务RPC接口,超时3秒resp, err := userClient.Register(context.Background(),req,callopt.WithRPCTimeout(3*time.Second),)if err != nil {log.Fatal(err) // RPC调用失败记录日志}c.String(200, resp.String()) // 返回RPC响应内容
}

这里服务依赖的kitex目前先不看,只用知道这里做了如下动作

通过hertz服务拿到了请求参数

往微服务进行传递参数

main函数
package mainimport ("log""api_gateway/user""github.com/cloudwego/hertz/pkg/app/server"
)func main() {// 创建路由分组(符合 RESTful 风格)// 第一级分组 /douyin 作为 API douyin := hz.Group("/douyin")// 第二级分组 /user 用于用户相关操作userGroup := douyin.Group("/user")// 注册用户注册接口,POST 方法对应创建操作// 处理函数指向 user 包的 Handler 方法userGroup.POST("/register/", user.Handler)// 启动 HTTP 服务,若失败则记录错误日志// Run() 会阻塞直到服务终止:ml-citation{ref="6" data="citationList"}if err := hz.Run(); err != nil {log.Fatal(err)}
}

可以看到这里和gin的操作差不多 gin的笔记:gin框架学习笔记_gin学习-CSDN博客

这里的主要逻辑:路由组注册

导入依赖

go mod tidy

kitex框架

kitex框架可以类比于grpc框架,grpc框架笔记:gRPC学习笔记记录以及整合gin开发-CSDN博客

也可以类比成dubbo和Java的SpringCloud

快速引入

本篇文章采用的协议为thrift

kitex工具下载

这个工具主要用来根据idl定义来自动生成代码,提高开发效率

go install github.com/cloudwego/kitex/tool/cmd/kitex@latest

idl定义

namespace go user// 用户注册请求
struct RegisterRequest {1: required string phone;       // 手机号2: required string verifyCode;  // 验证码
}// 用户注册响应
struct RegisterResponse {1: required bool success;       // 是否成功2: optional string message;     // 错误信息3: optional i64 userId;         // 用户ID4: optional string username;    // 自动生成的用户名
}// 用户登录请求
struct LoginRequest {1: required string phone;       // 手机号2: required string verifyCode;  // 验证码
}// 用户登录响应
struct LoginResponse {1: required bool success;       // 是否成功2: optional string message;     // 错误信息3: optional i64 userId;         // 用户ID4: optional string token;       // 登录令牌5: optional UserInfo userInfo;  // 用户信息
}// 用户基本信息
struct UserInfo {1: required i64 userId;         // 用户ID2: required string username;    // 用户名3: optional string avatar;      // 头像URL4: optional string signature;   // 个性签名5: optional i32 followCount;    // 关注数6: optional i32 followerCount;  // 粉丝数7: optional bool isFollow;      // 当前用户是否关注了该用户
}// 获取用户信息请求
struct GetUserInfoRequest {1: required i64 userId;         // 要查询的用户ID2: optional i64 currentUserId;  // 当前登录的用户ID
}// 获取用户信息响应
struct GetUserInfoResponse {1: required bool success;       // 是否成功2: optional string message;     // 错误信息3: optional UserInfo userInfo;  // 用户信息
}// 发送验证码请求
struct SendVerifyCodeRequest {1: required string phone;       // 手机号2: required i32 codeType;       // 验证码类型: 1-注册,2-登录,3-重置密码
}// 发送验证码响应
struct SendVerifyCodeResponse {1: required bool success;       // 是否成功2: optional string message;     // 错误信息
}// 用户服务接口定义
service UserService {// 用户注册RegisterResponse Register(1: RegisterRequest req);// 用户登录LoginResponse Login(1: LoginRequest req);// 获取用户信息GetUserInfoResponse GetUserInfo(1: GetUserInfoRequest req);// 发送验证码SendVerifyCodeResponse SendVerifyCode(1: SendVerifyCodeRequest req);
} 

这里定义了很多接口,包括用户请求参数结构定义,请求返回参数定义

自动生成代码

执行kitex指令

kitex -module video_douyin idl/user.thrift

返回

代码成功生成

user.go: 根据 IDL 生成的编解码文件,由 IDL 编译器生成

k-consts.go、k-user.go:kitex 专用的一些拓展内容

userservice:kitex 封装代码主要在这里

main.go入口函数定义

package mainimport ("log"user "video_douyin/kitex_gen/user/userservice""video_douyin/pkg/db"
)func main() {// 初始化MySQLif err := db.InitMySQL("root:901project@tcp(127.0.0.1:3306)/kanyuServer?charset=utf8mb4&parseTime=True&loc=Local"); err != nil {log.Fatalf("MySQL初始化失败: %v", err)}// 初始化Redisif err := db.InitRedis("127.0.0.1:6379", 0); err != nil {log.Fatalf("Redis初始化失败: %v", err)}// 创建UserServiceImpl实例并设置db和redisimpl := &UserServiceImpl{db:    db.DB,redis: db.Redis,}// 创建serversvr := user.NewServer(impl)// 运行服务if err := svr.Run(); err != nil {log.Fatalf("服务运行失败: %v", err)}
}

这里处理的作用:

1,初始化mysql

2,初始化redis

3,新建rpc服务实例注入db和redis

4,新建server

5,运行服务

依赖配置初始化db和redis

package dbimport ("context""fmt""sync""video_douyin/dal/model""github.com/go-redis/redis/v8""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/schema"
)var (DB        *gorm.DBRedis     *redis.ClientredisOnce sync.Once
)func InitMySQL(dsn string) error {var err errorDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true,// 禁用表名复数化NamingStrategy: schema.NamingStrategy{SingularTable: true,},})if err != nil {return err}// 自动迁移if err := DB.AutoMigrate(&model.User{}); err != nil {return err}return nil
}func InitRedis(addr string, db int) error {var initErr errorredisOnce.Do(func() {Redis = redis.NewClient(&redis.Options{Addr: addr,DB:   db,})if _, err := Redis.Ping(context.Background()).Result(); err != nil {initErr = fmt.Errorf("redis连接失败: %w", err)}})return initErr
}

model定义

这里实现了注册接口,所以定义user_db表

package modelimport ("gorm.io/gorm"
)type User struct {gorm.ModelPhone    string `gorm:"unique"`Password stringUsername stringAvatar   string
}// TableName 实现接口返回自定义表名
func (User) TableName() string {return "user_db" // 指定实际表名
}

接口核心服务逻辑

package mainimport ("context""crypto/rand""errors""fmt""log""math/big""time""video_douyin/dal/model"user "video_douyin/kitex_gen/user""github.com/go-redis/redis/v8""gorm.io/gorm"
)// UserServiceImpl implements the last service interface defined in the IDL.
type UserServiceImpl struct {db    *gorm.DBredis *redis.Client
}const (verifyCodePrefix = "verify_code:"tokenPrefix      = "user_token:"codeExpiration   = 5 * time.MinutetokenExpiration  = 24 * time.Hour
)// Register implements the UserServiceImpl interface
func (s *UserServiceImpl) Register(ctx context.Context, req *user.RegisterRequest) (resp *user.RegisterResponse, err error) {resp = user.NewRegisterResponse()if resp == nil {return nil, errors.New("failed to initialize response")}// 1. Validate the request parameterslog.Printf("进入rpc: %v\n", req.GetPhone())if req.GetPhone() == "" || req.GetVerifyCode() == "" {msg := "参数为空错误" // 改为包级变量或堆分配resp.SetMessage(&msg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return}// 2. 验证码校验storedCode, err := s.redis.Get(ctx, verifyCodePrefix+req.GetPhone()).Result()if err != nil || storedCode != req.GetVerifyCode() {msg := "验证码错误或已过期"resp.SetMessage(&msg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return resp, nil}// 3. 检查用户是否存在 存在则进入注册网页var existingUser model.Userif err := s.db.Where("phone = ?", req.GetPhone()).First(&existingUser).Error; err == nil {errorMsg := "用户已存在"resp.SetMessage(&errorMsg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return resp, nil}// 4. 创建用户newUser := model.User{Phone:    req.GetPhone(),Username: fmt.Sprintf("用户%s", req.GetPhone()[:4]),}if err := s.db.Create(&newUser).Error; err != nil {errorMsg := "注册失败"resp.SetMessage(&errorMsg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return resp, nil}// 5. 生成tokentoken, err := generateToken()if err != nil {errorMsg := "系统错误"resp.SetMessage(&errorMsg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return resp, nil}// 6. 存储tokenif err := s.redis.Set(ctx, tokenPrefix+token, newUser.ID, tokenExpiration).Err(); err != nil {errorMsg := "系统错误"resp.SetMessage(&errorMsg)resp.SetSuccess(false)if resp.Message != nil {log.Printf("错误详情: %s\n", *resp.Message)}return resp, nil}successMsg := "注册成功"resp.SetMessage(&successMsg)resp.SetSuccess(true)// resp.SetToken(token)// 需改下idlreturn resp, nil
}// Login implements the UserServiceImpl interface.
func (s *UserServiceImpl) Login(ctx context.Context, req *user.LoginRequest) (resp *user.LoginResponse, err error) {resp = user.NewLoginResponse()// 1. 校验参数异常if req.GetPhone() == "" || req.GetVerifyCode() == "" {errorMsg := "Invalid request parameters" // 声明字符串变量resp.SetMessage(&errorMsg)               // 传递指针resp.SetSuccess(true)}//2,验证码校验// 2. 验证码校验storedCode, err := s.redis.Get(ctx, verifyCodePrefix+req.GetPhone()).Result()if err != nil || storedCode != req.GetVerifyCode() {errorMsg := "验证码错误或已过期"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}// 3. 查询用户是否存在var existingUser model.Userif err := s.db.Where("phone = ?", req.GetPhone()).First(&existingUser).Error; err != nil {errorMsg := "用户不存在"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}// 4. 生成tokentoken, err := generateToken()if err != nil {errorMsg := "系统错误"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}// 5. 存储tokenif err := s.redis.Set(ctx, tokenPrefix+token, existingUser.ID, tokenExpiration).Err(); err != nil {errorMsg := "系统错误"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}successMsg := "登录成功"resp.SetMessage(&successMsg)resp.SetSuccess(true)// resp.SetToken(token) 需加上返回给前端return resp, nil
}// GetUserInfo implements the UserServiceImpl interface.
func (s *UserServiceImpl) GetUserInfo(ctx context.Context, req *user.GetUserInfoRequest) (resp *user.GetUserInfoResponse, err error) {resp = user.NewGetUserInfoResponse()// 1. 参数校验if req.GetUserId() == 0 {errorMsg := "Invalid user id"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}// 2. 查询用户信息var userModel model.Userif err := s.db.Where("id = ?", req.GetUserId()).First(&userModel).Error; err != nil {if errors.Is(err, gorm.ErrRecordNotFound) {errorMsg := "User not found"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}errorMsg := "Database error"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}// 3. 构造UserInfo结构体userInfo := &user.UserInfo{UserId:   userModel.ID,Username: userModel.Username,Avatar:   &userModel.Avatar,}// 4. 设置响应resp.SetSuccess(true)resp.SetUserInfo(userInfo)return resp, nil
}// SendVerifyCode implements the UserServiceImpl interface.
func (s *UserServiceImpl) SendVerifyCode(ctx context.Context, req *user.SendVerifyCodeRequest) (resp *user.SendVerifyCodeResponse, err error) {resp = user.NewSendVerifyCodeResponse()phone := req.GetPhone()// 1. 校验参数异常if phone == "" {errorMsg := "Invalid request parameters" // 声明字符串变量resp.SetMessage(&errorMsg)               // 传递指针resp.SetSuccess(false)}//2,查询db看用户手机号是否存在CheckPhoneExists(s.db, phone)//3, 生成验证码code, _ := generateCaptcha()log.Printf("code: %s", code) // 记录请求参数//4. 保存验证码到redisif err := s.saveCodeToRedis(phone, code); err != nil {errorMsg := "Failed to save verification code"resp.SetMessage(&errorMsg)resp.SetSuccess(false)return resp, nil}//5. 发送验证码successMsg := "success"      // 声明字符串变量resp.SetMessage(&successMsg) // 传递指针resp.SetSuccess(true)return resp, nil
}func generateCaptcha() (string, error) {// 生成一个0到999999之间的随机数(6位数)n, err := rand.Int(rand.Reader, big.NewInt(1000000)) // 1000000是10^6,即最大值+1if err != nil {return "", err}// 将随机数转换为字符串,并确保长度为6位(不足时前面补0)captcha := fmt.Sprintf("%06d", n) // %06d确保至少6位数字,不足时前面补0return captcha, nil
}// 生成token
func generateToken() (string, error) {b := make([]byte, 32)if _, err := rand.Read(b); err != nil {return "", err}return fmt.Sprintf("%x", b), nil
}// CheckPhoneExists 检查手机号是否已存在
func CheckPhoneExists(db *gorm.DB, phone string) (bool, error) {var user = &model.User{}result := db.Where("phone = ?", phone).First(user)if result.Error != nil {if result.Error == gorm.ErrRecordNotFound {return false, nil // 手机号不存在}return false, result.Error // 查询出错}return true, nil // 手机号已存在
}// 存入redis
func (s *UserServiceImpl) saveCodeToRedis(phone, code string) error {key := verifyCodePrefix + phonereturn s.redis.Set(context.Background(), key, code, codeExpiration).Err()
}

导入依赖

go mod tidy

服务启动与测试

rpc服务启动

http服务启动

请求

返回

看db存储

源码

GitHub - enjoykanyu/video_feed: 仿抖音后端项目 springcloud+springboot+mysql+redis+rabiitmq

觉得不错的话可以帮点个star呗,感谢

参考

Hertz | CloudWeGo

Kitex | CloudWeGo

相关文章:

Hertz+Kitex快速上手开发

本篇文章以用户注册接口为例,快速上手HertzKitex 以用户注册接口来演示hertz结合kitex实现网关微服务架构的最简易版本 项目结构 api- gateway:网关实现,这里采用hertz框架 idl:接口定义用来生成kitex代码 kitex_gen&#xff…...

线程池配置经验总结

1. 核心线程数配置(corePoolSize) 1.1 核心线程数的配置影响因素 CPU核心数 CPU密集型任务:核心线程数 ≈ CPU核心数 1IO密集型任务:核心线程数 ≈ CPU核心数 (1 平均等待时间/平均计算时间) 一般经验值:2 CPU核心数 内存大小&#xff…...

机器学习课程设计报告 —— 基于二分类的岩石与金属识别模型

机器学习课程设计报告 题 目: 基于二分类的岩石与金属识别模型 专 业: 机器人工程 学生姓名: XXX 指导教师: XXX 完成日期&#xff1a…...

分词算法BPE详解和CLIP的应用

一、TL;DR BPE通过替换相邻最频繁的字符和持续迭代来实现压缩CLIP对text进行标准化和预分词后,对每一个单词进行BPE编码和查表,完成token_id的转换 二、BPE算法 2.1 核心思想和原理 paper:Neural Machine Translation of Rare…...

STM32F103_Bootloader程序开发02 - Bootloader程序架构与STM32F103ZET6的Flash内存规划

导言 在工业设备和机器人项目中,固件远程升级能力已成为提升设备维护性与生命周期的关键手段。本文将围绕STM32平台,系统性介绍一个简洁、可靠的Bootloader程序设计思路。 我们将Bootloader核心流程划分为五大功能模块: 启动入口与升级模式判…...

通过Auto平台与VScode搭建远程开发环境(以Stable Diffusion Web UI为例)

文章目录 Stable Diffusion Web UI一、🎯主要功能概述二、🧠支持的主要模型体系三、📦安装方式简述✅ 一、前提准备✅ 二、安装步骤混乱版本(仅用于记录测试过程)第一步:克隆仓库(使用清华大学镜…...

Windows_Rider C#语言开发环境构建

Windows_Rider C#语言开发环境构建 一、C#语言简介历史背景语言特点应用领域开发工具未来发展方向 二、Rider简介功能特点支持的语言免费版本最新更新 三、开发环境构建(一)安装 JetBrains Rider(二)安装 .NET SDK(三&…...

Unity 打包程序全屏置顶无边框

该模块功能: 1. 打包无边框 2. 置顶 3. 不允许切屏 4.多显示器状态下,程序只在主显示上运行 5.全屏 Unity 打包设置: 如果更改打包设置,最好将Version版本增加一下,否则可能不会覆盖前配置文件 代码: 挂在场景中即可 using UnityEngine; using System; // 确保这行存…...

GAMES104 Piccolo引擎搭建配置

操作系统:windows11 家庭版 inter 17 12 th 显卡:amd 运行内存:>12 1、如何构建? 在github下载:网址如下 https://github.com/BoomingTech/Piccolo 下载后安装 git、vs2022 Git Visual Studio 2022 IDE - …...

第 29 场 蓝桥·算法入门赛

1. 不油腻的星座 "我们只欢迎不油腻的星座!" 在「非哺乳动物星座联盟」的派对上,主持人突然宣布:"请在场的 12 星座中,名字里包含哺乳动物的立刻离场",结果白羊、金牛、狮子、摩羯 44 个星座红着脸…...

用service 和 SCAN实现sqlplus/jdbc连接Oracle 11g RAC时负载均衡

说明 11.2推出的SCAN ,简化了客户端连接(当增加或者减少RAC实例时,不需要修改客户端配置,并且scan listener有各个实例的负载情况,可以实现连接时负载均衡。 不过客户端需要使用专门建立的service,而不能用RAC数据库…...

Jenkins 中获取构建触发用户的完整指南

在持续集成(CI/CD)流程中,追踪构建的触发用户是排查问题、审计操作或通知相关人员的重要需求。然而,Jenkins 默认不直接暴露触发构建的用户信息,尤其是在自动触发场景下。本文将详细介绍 多种获取 Jenkins 构建触发用户的方法,涵盖插件使用、脚本编写和 API 查询,并提供…...

防火墙流量管理

带宽管理介绍 针对企业用户流量,防火墙提供了带宽管理功能,基于出/入接口、源/目的安全区域、源/目的地址、时间段、报文DSCP优先级等信息,对通过自身的流量进行管理和控制。 带宽管理提供带宽限制、带宽保证和连接数限制功能,可…...

uniapp+ts 多环境编译

1. 创建项目 npx degit dcloudio/uni-preset-vue#vite-ts [项目名称] 2.创建env目录 多环境配置文件命名为.env.别名 添加index.d.ts interface ImportMetaEnv{readonly VITE_ENV:string,readonly UNI_PLATFORM:string,readonly VITE_APPID:string,readonly VITE_NAME:stri…...

Linux系统移植①:uboot概念

Linux系统移植①:uboot概念 uboot概念 1、uboot是一个比较复杂的裸机程序。 2、uboot就是一个bootloader,作用就是用原于启动Linux或其他系统。uboot最主要的工作就是初始化DDR。因为Linux是运行再DDR里面的。一般Linux镜像zImage(uImage)设…...

linux 学习之位图(bitmap)数据结构

bitmap 可以高效地表示大量的布尔值,并且在许多情况下可以提供快速的位操作。 1 定义 enum device_state{DOWN,DOEN_DONE,MAILBOX_READY,MAILBOX_PENDING,STATE_BUILD };DECLARE_BITMAP(state,STATE_BUILD);相当于》u32 state[BITS_TO_LONGS(4)] BIT…...

DAY 35

import torch import torch.nn as nn import torch.optim as optim from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler import time import matplotlib.pyplot as plt# 设置GPU设…...

理论篇一:了解webpack是什么,能解决什么问题,如何使用

Webpack 是前端工程化的核心工具之一,它的核心目标是将前端项目中的各种资源(JS、CSS、图片等)高效打包成浏览器可运行的静态文件。以下是系统化的解答: 一、Webpack 是什么? 1. 定义 Webpack 是一个 静态模块打包工具(Static Module Bundler),它通过分析项目的依赖关…...

AWS EC2实例安全远程访问最佳实践

EC2 远程连接方案对比 远程访问 Amazon EC2 实例主要有以下四种方式: Secure Shell (SSH) 远程访问AWS Systems Manager 会话管理器适用于 Linux 实例的 EC2 Serial ConsoleAmazon EC2 Instance Connect SSH 远程访问 SSH(Secure Shell)广…...

集群、容器云与裸金属服务器的全面对比分析

文章目录 引言 集群 2.1 定义 2.2 特点 2.3 应用场景 容器云 3.1 定义 3.2 核心功能 3.3 应用场景 裸金属 4.1 定义 4.2 特点 4.3 应用场景 三者的区别 5.1 架构与性能 5.2 管理与运维 5.3 成本与灵活性 总结 1. 引言 在云计算和数据中心领域,50…...

【强化学习】#7 基于表格型方法的规划和学习

主要参考学习资料:《强化学习(第2版)》[加]Richard S.Suttion [美]Andrew G.Barto 著 文章源文件:https://github.com/INKEM/Knowledge_Base 本章更是厘清概念厘到头秃,如有表达不恰当之处还请多多指教—— 概述 环境…...

EasyRTC嵌入式音视频通信SDK一对一音视频通信,打造远程办公/医疗/教育等场景解决方案

一、方案概述​ 数字技术发展促使在线教育、远程医疗等行业对一对一实时音视频通信需求激增。传统方式存在低延迟、高画质及多场景适配不足等问题,而EasyRTC凭借音视频处理、高效信令交互与智能网络适配技术,打造稳定低延迟通信,满足基础通信…...

Linux/aarch64架构下安装Python的Orekit开发环境

1.背景 国产化趋势越来越强,从软件到硬件,从操作系统到CPU,甚至显卡,就产生了在国产ARM CPU和Kylin系统下部署Orekit的需求,且之前的开发是基于Python的,需要做适配。 2.X86架构下安装Python/Orekit开发环…...

网络安全-等级保护(等保) 3-2-1 GB/T 28449-2019 第6章 方案编制活动

################################################################################ GB/T 28449-2019《信息安全技术 网络安全等级保护测评过程指南》是规定了等级测评过程,是纵向的流程,包括:四个基本测评活动:测评准备活动、方案编制活…...

Oracle Enqueue Names

Oracle Enqueue Names Enqueue(排队锁)是Oracle数据库中用于协调多进程并发访问共享资源的锁机制。 This appendix lists Oracle enqueues. Enqueues are shared memory structures (locks) that serialize access to database resources. They can be…...

【免费使用】剪Y专业版 8.1/CapCut 视频编辑处理,素材和滤镜

—————【下 载 地 址】——————— 【​本章下载一】:https://pan.xunlei.com/s/VOQxk38EUe3_8Et86ZCH84JsA1?pwdkp7h# 【​本章下载二】:https://pan.quark.cn/s/388008091ab4 【​本章下载三】:https://drive.uc.cn/s/d5ae5c725637…...

【DCGMI专题1】---DCGMI 在 Ubuntu 22.04 上的深度安装指南与原理分析(含架构图解)

目录 一、DCGMI 概述与应用场景 二、Ubuntu 22.04 系统准备 2.1 系统要求 2.2 环境清理(可选) 三、DCGMI 安装步骤(详细图解) 3.1 安装流程总览 3.2 分步操作指南 3.2.1 系统更新与依赖安装 3.2.2 添加 NVIDIA 官方仓库 3.2.3 安装数据中心驱动与 DCGM 3.2.4 服务…...

道德经总结

道德经 《道德经》是中国古代伟大哲学家老子所著,全书约五千字,共81章,分为“道经”(1–37章)和“德经”(38–81章)两部分。 《道德经》是一部融合哲学、政治、人生智慧于一体的经典著作。它提…...

实现rpc通信机制(待定)

一、概述 (1)rpc(remote procedure call, 远程接口调用),就像在本地调用函数一样,是应用组成服务内部分布式的基础功能。应用场景是在内网中的计算,比如:(a) 为上传的一张图片加水印、&#xf…...

MATLAB 2023b 配电柜温度报警系统仿真

MATLAB 2023b 配电柜温度报警系统仿真 下面是一个配电柜温度报警系统的MATLAB仿真代码,包含温度监测、断路器控制和声光报警功能。 classdef ElectricalPanelTemperatureAlertSystem < handleproperties% 系统参数TemperatureThreshold = 94; % 温度阈值(摄氏度)Simulati…...