网站首页 > 技术文章 正文
主要编写资源的通用信息模块,protobuf的数据结构代码,和逻辑实现的代码
resource模块
保存资源的通用信息,
resource的proto文件
apps/resource/pb/resource.proto—新建
syntax = "proto3";
package go8.devcloud.cmdb.resource;
option go_package = "gitee.com/go-course/go8/projects/devcloud/cmdb/apps/resource";
message ResourceSet {
// @gotags: json:"total"
int64 total = 1;
// @gotags: json:"items"
repeated Resource items = 2;
}
message Resource {
// 资源元数据信息
// @gotags: json:"meta"
Meta meta = 1;
// 资源规格信息
// @gotags: json:"spec"
Spec spec = 2;
// 资源费用
// @gotags: json:"cost"
Cost cost = 3;
// 资源状态
// @gotags: json:"status"
Status status = 4;
// 资源标签
// @gotags: json:"tags"
repeated Tag tags = 5;
// 关联资源
// @gotags: json:"related_resources"
repeated Resource related_resources = 6;
}
// 资源元数据信息, 静态数据
message Meta {
// 全局唯一Id, 直接使用个云商自己的Id
// @gotags: json:"resource_id" validate:"required"
string resource_id = 1;
// 资源所属域
// @gotags: json:"domain" validate:"required"
string domain = 2;
// 资源所属空间
// @gotags: json:"namespace" validate:"required"
string namespace = 3;
// 资源所属环境
// @gotags: json:"env"
string env = 4;
// 同步时间
// @gotags: json:"sync_at" validate:"required"
int64 sync_at = 5;
// 用于同步的凭证ID, 该资源绑定的API Key, 通过该Key可以操作资源
// @gotags: json:"credential_id"
string credential_id = 6;
// 创建时间
// @gotags: json:"create_at"
int64 create_at = 7;
// 序列号
// @gotags: json:"serial_number"
string serial_number = 9;
}
enum VENDOR {
ALIYUN = 0;
TENCENT = 1;
HUAWEI = 2;
VSPHERE = 3;
AMAZON = 4;
}
enum TYPE {
// 业务资源
HOST = 0;
RDS = 1;
REDIS = 2;
BUCKET = 3;
DISK = 4;
LB = 5;
DOMAIN = 6;
EIP = 7;
MONGODB = 8;
// 子资源
DATABASE = 100;
ACCOUNT = 101;
// 未知资源
OTHER = 199;
// 辅助资源
BILL = 200;
ORDER = 201;
}
// 资源规格信息, 动态数据, 申请资源的规格信息
message Spec {
// 厂商
// @gotags: json:"vendor"
VENDOR vendor = 1;
// 资源类型
// @gotags: json:"resource_type"
TYPE resource_type = 2;
// 地域
// @gotags: json:"region"
string region = 3;
// 区域
// @gotags: json:"zone"
string zone = 4;
// 资源所属账号
// @gotags: json:"owner"
string owner = 5;
// 名称
// @gotags: json:"name"
string name = 6;
// 种类
// @gotags: json:"category"
string category = 7;
// 规格
// @gotags: json:"type"
string type = 8;
// 描述
// @gotags: json:"description"
string description = 9;
// 过期时间
// @gotags: json:"expire_at"
int64 expire_at = 10;
// 更新时间
// @gotags: json:"update_at"
int64 update_at = 11;
// 是否开启实例释放保护
// @gotags: json:"release_protection"
optional bool release_protection = 12;
// 资源占用Cpu数量
// @gotags: json:"cpu"
int32 cpu = 15;
// GPU数量
// @gotags: json:"gpu"
int32 gpu = 16;
// 资源使用的内存
// @gotags: json:"memory"
int32 memory = 17;
// 资源使用的存储
// @gotags: json:"storage"
int32 storage = 18;
// 公网IP带宽, 单位M
// @gotags: json:"band_width"
int32 band_width =19;
}
enum PayMode {
// 预付费, 包年包月
PRE_PAY = 0;
// 按需
POST_PAY = 1;
// 预定
RESERVED_PAY = 2;
}
// 资源价格,动态数据
message Cost {
// 实例付费方式
// @gotags: json:"pay_mode"
optional PayMode pay_mode = 1;
// 付费方式详情
// @gotags: json:"pay_mode_detail"
string pay_mode_detail = 2;
// 官网价,原价(分)
// @gotags: json:"sale_price"
double sale_price = 3;
// 实际支付金额(分)
// @gotags: json:"real_cost"
double real_cost = 4;
// 折扣率
// @gotags: json:"policy"
double policy = 5;
// 单价(分)
// @gotags: json:"unit_price"
double unit_price = 6;
}
// 资源价格,动态数据
message Status {
// 资源当前状态
// @gotags: json:"phase"
string phase = 1;
// 实例锁定模式; Unlock:正常;ManualLock:手动触发锁定;LockByExpiration:实例过期自动锁定;LockByRestoration:实例回滚前的自动锁定;LockByDiskQuota:实例空间满自动锁定
// @gotags: json:"lock_mode"
string lock_mode = 2;
// 锁定原因
// @gotags: json:"lock_reason"
string lock_reason = 3;
// 资源访问地址
// 公网IP, 或者域名
// @gotags: json:"public_ip"
string public_ip = 4;
// 内网IP, 或者域名
// @gotags: json:"private_ip"
string private_ip = 5;
}
// 标签用途
enum TAG_PURPOSE {
// 用于资源分组
GROUP = 0;
// 系统使用标签, 表示被其他系统引用, 比如应用关联标签
SYSTEM = 1;
// 用于资源监控
MONITOR = 2;
}
// 资源价格,动态数据
message Tag {
// 标签的类型
// @gotags: json:"purpose"
TAG_PURPOSE purpose = 1;
// 标签的Key
// @gotags: json:"key" validate:"lte=255,required"
string key = 2;
// 标签的值
// @gotags: json:"value" validate:"lte=255,required"
string value = 3;
// 标签的值的描述, 通常用于展示
// @gotags: json:"describe"
string describe = 4;
// 标签权重, 针对同一个key, 多个value场景, 默认值1
// @gotags: json:"weight"
int64 weight = 5;
// 是否是只读标签
// @gotags: json:"read_only"
bool read_only = 6;
// 标签是否隐藏, 用于控制是否在前端展示
// @gotags: json:"hidden"
bool hidden = 7;
}
apps/resource/pb/rpc.proto—新建
syntax = "proto3";
package go8.devcloud.cmdb.resource;
option go_package = "gitee.com/go-course/go8/projects/devcloud/cmdb/apps/resource";
import "apps/resource/pb/resource.proto";
import "github.com/infraboard/mcube/pb/page/page.proto";
service RPC {
// 保存资源
rpc SaveResource(Resource) returns(Resource);
// 查询资源
rpc QueryResource(QueryResourceRequest) returns(ResourceSet);
}
message QueryResourceRequest {
// 分页参数
// @gotags: json:"page"
infraboard.mcube.page.PageRequest page = 1;
// 资源所属域
// @gotags: json:"domain"
string domain = 2;
// 资源所属空间
// @gotags: json:"namespace"
string namespace = 3;
// 资源所属环境
// @gotags: json:"env"
string env = 4;
// 资源类型
// @gotags: json:"type"
optional TYPE type = 8;
// 服务商中的状态
// @gotags: json:"status"
string status = 9;
}
make gen生成代码
有时候修改了proto文件,正常make gen可以重新生成,如果不行,重启一下IDE
resource模块的全局app
apps/resource/app.go
设置resource模块对应的模块名,校验,接口以及orm的表名
const (
AppName = "resource"
)
var (
validate = validator.New()
)
type Service interface {
RPCServer
}
// 默认用TableName来指定写入表的名称
func (m *Meta) TableName() string {
return "resource_meta"
}
func (r *Resource) Validate() error {
validateStructs := []any{r.Meta, r.Spec, r.Cost}
for _, v := range validateStructs {
err := validate.Struct(v)
if err != nil {
return err
}
}
return nil
}
resource的逻辑实现部分
apps/resource/impl/impl.go
将模块实现IOC
var (
// Service 服务实例
svr = &service{}
)
type service struct {
db *gorm.DB
log logger.Logger
resource.UnimplementedRPCServer
}
func (s *service) Config() error {
db, err := conf.C().MySQL.ORM()
db = db.Clauses(clause.OnConflict{
UpdateAll: true,
})
if err != nil {
return err
}
s.db = db
s.log = zap.L().Named(s.Name())
return nil
}
func (s *service) Name() string {
return resource.AppName
}
func (s *service) Registry(server *grpc.Server) {
resource.RegisterRPCServer(server, svr)
}
func init() {
app.RegistryGrpcApp(svr)
app.RegistryInternalApp(svr)
}
mysql的orm—conf/config.go
func (m *mysql) ORM() (*gorm.DB, error) {
conn, err := m.GetDB()
if err != nil {
return nil, err
}
return gorm.Open(orm_mysql.New(orm_mysql.Config{
Conn: conn,
}), &gorm.Config{
// 执行任何 SQL 时都创建并缓存预编译语句,可以提高后续的调用速度
PrepareStmt: true,
// 对于写操作(创建、更新、删除),为了确保数据的完整性,GORM 会将它们封装在事务内运行。
// 但这会降低性能,如果没有这方面的要求,您可以在初始化时禁用它,这将获得大约 30%+ 性能提升
SkipDefaultTransaction: true,
// 要有效地插入大量记录,请将一个 slice 传递给 Create 方法
CreateBatchSize: 200,
})
apps/resource/impl/resource_dao.go—保存resource
func (s *service) save(ctx context.Context, res *resource.Resource) (err error) {
// 开启事务
tx := s.db.WithContext(ctx).Begin()
defer func() {
if err != nil {
tx.Rollback()
return
}
err := tx.Commit().Error
if err != nil {
s.log.Errorf("commit error, %s", err)
}
}()
rid := &ResourceId{ResourceId: res.Meta.ResourceId}
err = tx.Create(res.Meta).Error
if err != nil {
return
}
err = tx.Create(&Spec{Spec: res.Spec, ResourceId: rid}).Error
if err != nil {
return
}
err = tx.Create(&Status{Status: res.Status, ResourceId: rid}).Error
if err != nil {
return
}
err = tx.Create(&Cost{Cost: res.Cost, ResourceId: rid}).Error
if err != nil {
return
}
err = tx.Where("resource_id = ?", res.Meta.ResourceId).Delete(&Tag{}).Error
if err != nil {
return
}
for i := range res.Tags {
err = tx.Create(&Tag{Tag: res.Tags[i], ResourceId: rid}).Error
if err != nil {
return
}
}
return
}
apps/resource/impl/resource.go
func (s *service) SaveResource(ctx context.Context, res *resource.Resource) (
*resource.Resource, error) {
// 比如检查
if err := res.Validate(); err != nil {
return nil, err
}
// 入库
err := s.save(ctx, res)
if err != nil {
return nil, err
}
return res, nil
}
apps/resource/impl/resource_dao.go
添加查询的方法
func (s *service) query(ctx context.Context, res *resource.QueryResourceRequest) (
*resource.ResourceSet, error) {
// 首先查询Meta表
// LEFT JOIN
return nil, nil
}
猜你喜欢
- 2024-09-09 Go语言进阶之Go语言高性能Web框架Iris项目实战-完善用户管理EP04
- 2024-09-09 数据库与 Go 的交互(go数据库和kegg数据库)
- 2024-09-09 七爪源码:N+1 查询如何烧毁您的数据库
- 2024-09-09 Go的安全编程和防御性编程(防止代码注入)
- 2024-09-09 Vue3+Go 仿抖音项目架构设计与实现
- 2024-09-09 腾讯Go安全指南(腾讯官网最新安全公告)
- 2024-09-09 Grails指南24查询高阶(grails中文参考手册)
- 2024-09-09 Redis优化高并发下的秒杀性能(redis秒杀高并发代码)
- 2024-09-09 10.Go语言编写个人博客 文章分类(基于golang的个人博客系统)
- 2024-09-09 Golang database/sql源码分析(golang sqlmock)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)