【Go語言實戰(zhàn)】 (11) go-micro微服務(wù) 實現(xiàn)簡單備忘錄 (下) | 備忘錄模塊

      網(wǎng)友投稿 703 2025-03-31

      文章目錄


      寫在前面

      1. RabbitMQ創(chuàng)建備忘錄

      1.1 導(dǎo)入配置

      1.2 proto

      1.2.1 taskModels.proto

      1.2.2 taskService.proto

      1.3 寫入數(shù)據(jù)

      1.4 讀取數(shù)據(jù)

      2. 備忘錄其他操作

      2.1 獲取備忘錄列表

      2.2 獲取備忘錄詳情

      2.3 更新備忘錄

      2.4 注冊到etcd中

      3. 接入網(wǎng)關(guān)

      3.1 接入路由

      3.2 編寫接口(創(chuàng)建備忘錄為例子)

      3.3 測試

      寫在前面

      這一章節(jié)我們繼續(xù)前一章的內(nèi)容,將備忘錄模塊完善,我們將使用RabbitMQ作為消息隊列去創(chuàng)建備忘錄

      1. RabbitMQ創(chuàng)建備忘錄

      1.1 導(dǎo)入配置

      導(dǎo)入配置

      [rabbitmq] RabbitMQ = amqp RabbitMQUser = guest RabbitMQPassWord = guest RabbitMQHost = localhost RabbitMQPort = 5672

      1

      2

      3

      4

      5

      6

      加載配置

      func LoadRabbitMQ(file *ini.File) { RabbitMQ = file.Section("rabbitmq").Key("RabbitMQ").String() RabbitMQUser = file.Section("rabbitmq").Key("RabbitMQUser").String() RabbitMQPassWord = file.Section("rabbitmq").Key("RabbitMQPassWord").String() RabbitMQHost = file.Section("rabbitmq").Key("RabbitMQHost").String() RabbitMQPort = file.Section("rabbitmq").Key("RabbitMQPort").String() }

      1

      2

      3

      4

      5

      6

      7

      連接RabbitMQ

      // MQ rabbitMQ鏈接單例 var MQ *amqp.Connection // 初始化rabbitMQ鏈接 func RabbitMQ(connString string) { conn, err := amqp.Dial(connString) if err != nil { panic(err) } MQ = conn }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      1.2 proto

      task/services/protos

      1.2.1 taskModels.proto

      定義了task的proto模型

      syntax="proto3"; package services; option go_package ="./;protos"; message TaskModel{ //@inject_tag: json:"Id" form:"Id" uint64 Id = 1; //@inject_tag: json:"Uid" form:"Uid" uint64 Uid = 2; //@inject_tag: json:"Title" form:"Title" string Title = 3; //@inject_tag: json:"Content" form:"Content" string Content = 4; //@inject_tag: json:"StartTime" form:"StartTime" int64 StartTime = 5; //@inject_tag: json:"EndTime" form:"EndTime" int64 EndTime = 6; //@inject_tag: json:"Status" form:"Status" int64 Status = 7; //@inject_tag: json:"CreateTime" form:"CreateTime" int64 CreateTime = 8; //@inject_tag: json:"UpdateTime" form:"UpdateTime" int64 UpdateTime = 9; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      執(zhí)行protoc生成pb文件

      protoc --proto_path=. --micro_out=. --go_out=. taskModels.proto

      1

      1.2.2 taskService.proto

      定義了taskRequest,task的請求參數(shù)。

      定義了TaskListResponse,task列表的響應(yīng)參數(shù)。

      定義了TaskDetailResponse,task列表的詳細(xì)信息。

      定義了TaskService,都是定義一些增刪改查的服務(wù)。

      syntax="proto3"; package services; import "taskModels.proto"; option go_package = "./;protos"; message TaskRequest{ //@inject_tag: json:"Id" form:"Id" uint64 Id = 1; //@inject_tag: json:"Uid" form:"Uid" uint64 Uid = 2; //@inject_tag: json:"Title" form:"Title" string Title = 3; //@inject_tag: json:"Content" form:"Content" string Content = 4; //@inject_tag: json:"StartTime" form:"StartTime" int64 StartTime = 5; //@inject_tag: json:"EndTime" form:"EndTime" int64 EndTime = 6; //@inject_tag: json:"Status" form:"Status" int64 Status = 7; // @inject_tag: json:"Start" form:"Start" uri:"Start" uint32 Start = 8; // @inject_tag: json:"Limit" form:"Limit" uri:"Limit" uint32 Limit = 9; } message TaskListResponse{ repeated TaskModel TaskList=1; // @inject_tag: json:"Count" uint32 Count=2; } message TaskDetailResponse{ TaskModel TaskDetail=1; } service TaskService{ rpc CreateTask(TaskRequest) returns(TaskDetailResponse); rpc GetTasksList(TaskRequest) returns(TaskListResponse); rpc GetTask(TaskRequest) returns(TaskDetailResponse); rpc UpdateTask(TaskRequest) returns(TaskDetailResponse); rpc DeleteTask(TaskRequest) returns(TaskDetailResponse); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      執(zhí)行protoc生成pb文件

      protoc --proto_path=. --micro_out=. --go_out=. taskService.proto

      1

      1.3 寫入數(shù)據(jù)

      task/core/taskService.go

      我們在這個go文件中將數(shù)據(jù)寫入RabbitMQ當(dāng)中。

      連接通道

      ch, err := model.MQ.Channel() if err != nil { err = errors.New("rabbitMQ err:" + err.Error()) return err }

      1

      2

      3

      4

      5

      聲明通道隊列

      q, err := ch.QueueDeclare("task_queue", true, false, false, false, nil) if err != nil { err = errors.New("rabbitMQ err:" + err.Error()) return err }

      1

      2

      3

      4

      5

      將請求的參數(shù)序列化,發(fā)布到隊列中

      body, _ := json.Marshal(req) err = ch.Publish("", q.Name, false, false, amqp.Publishing{ DeliveryMode: amqp.Persistent, ContentType: "application/json", Body: body, })

      1

      2

      3

      4

      5

      6

      1.4 讀取數(shù)據(jù)

      mq-server/services/task.go

      從RabbitMQ中接收數(shù)據(jù)信息再寫入數(shù)據(jù)庫中

      打開Channel

      ch, err := model.MQ.Channel()

      1

      從task_queue通道中獲取消息

      q, err := ch.QueueDeclare("task_queue", true, false, false, false, nil) if err != nil { panic(err) }

      1

      【Go語言實戰(zhàn)】 (11) go-micro微服務(wù) 實現(xiàn)簡單備忘錄 (下) | 備忘錄模塊

      2

      3

      4

      name:隊列名稱;

      durable:是否持久化,隊列存盤,true服務(wù)重啟后信息不會丟失,影響性能;

      autoDelete:是否自動刪除;

      noWait:是否非阻塞,true為是,不等待RMQ返回信息;

      args:參數(shù),傳nil即可;

      exclusive:是否設(shè)置排他

      消息ACK保證了消息不會丟失,但是當(dāng)rabbitMQ Server停止(不是consumer 掛掉)的時候,我們的所有消息都會丟失。針對這種情況,我們先確保消息隊列的持久化,設(shè)置消息隊列的durable選項為true

      公平分派消息

      err = ch.Qos(1, 0, false) if err != nil { panic(err) }

      1

      2

      3

      4

      設(shè)置Qos,設(shè)置預(yù)取大小prefetch,當(dāng)prefetch=1時,表示在沒收到consumer的ACK消息之前,只會為其consumer分派一個消息。

      讀出數(shù)據(jù)

      msgs, err := ch.Consume(q.Name, "", false, false, false, false, nil)

      1

      從通道中讀出數(shù)據(jù)

      將通道的信息,反系列化,然后在數(shù)據(jù)庫中創(chuàng)建。

      go func() { for d := range msgs { var p model.Task err := json.Unmarshal(d.Body, &p) if err != nil { panic(err) } fmt.Println("d.Body",string(d.Body)) model.DB.Create(&p) log.Printf("Done") _ = d.Ack(false) // 確認(rèn)消息,必須為false } }()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      2. 備忘錄其他操作

      構(gòu)造一個服務(wù)

      type TaskService struct { }

      1

      2

      3

      2.1 獲取備忘錄列表

      傳入的參數(shù):上下文信息,請求參數(shù),響應(yīng)參數(shù)。

      func (*TaskService) GetTasksList(ctx context.Context, req *services.TaskRequest, res *services.TaskListResponse) error { if req.Limit == 0 { req.Limit = 6 } //在數(shù)據(jù)庫查找值 var productData []model.Task var count uint32 err := model.DB.Offset(req.Start).Limit(req.Limit).Where("uid=?", req.Uid).Find(&productData).Error if err != nil { err = errors.New("mysql err:" + err.Error()) return err } err = model.DB.Model(&model.Task{}).Where("uid=?", req.Uid).Count(&count).Error if err != nil { err = errors.New("mysql err:" + err.Error()) return err } //序類化備忘錄列表 var taskRes []*services.TaskModel for _, item := range productData { taskRes = append(taskRes, BuildTask(item)) } //序列化后的結(jié)果賦給response res.TaskList = taskRes res.Count = count return nil }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      2.2 獲取備忘錄詳情

      func (*TaskService) GetTask(ctx context.Context, req *services.TaskRequest, res *services.TaskDetailResponse) error { //在數(shù)據(jù)庫查找值 productData := model.Task{} err := model.DB.First(&productData, req.Id).Error if err != nil { err = errors.New("mysql err:" + err.Error()) return err } //序類化商品 productRes := BuildTask(productData) //序列化后的結(jié)果賦給response res.TaskDetail = productRes return nil }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      2.3 更新備忘錄

      func (*TaskService) UpdateTask(ctx context.Context, req *services.TaskRequest, res *services.TaskDetailResponse) error { //在數(shù)據(jù)庫查找值 taskData := model.Task{} err := model.DB.Model(model.Task{}).Where("id = ? AND uid = ?",req.Id,req.Uid).First(&taskData).Error if err != nil { err = errors.New("mysql err:" + err.Error()) return err } //將要更新的數(shù)據(jù)賦值給結(jié)構(gòu)體 taskData.Title = req.Title taskData.Status = int(req.Status) taskData.Content = req.Content //update err = model.DB.Save(&taskData).Error if err != nil { err = errors.New("mysql err:" + err.Error()) return err } //序列化后的結(jié)果賦給response res.TaskDetail = BuildTask(taskData) return nil }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      2.4 注冊到etcd中

      注冊etcd

      etcdReg := etcd.NewRegistry( registry.Addrs("127.0.0.1:2379"), )

      1

      2

      3

      得到微服務(wù)實例

      // 1. 得到微服務(wù)實例 microService := micro.NewService( micro.Name("rpcTaskService"), // 設(shè)置微服務(wù)名字,用來訪問的 micro.Address("127.0.0.1:8083"), micro.Registry(etcdReg), )

      1

      2

      3

      4

      5

      6

      初始化

      microService.Init()

      1

      服務(wù)注冊

      將用戶服務(wù)注冊到etcd中

      _ = services.RegisterTaskServiceHandler(microService.Server(), new(core.TaskService))

      1

      啟動微服務(wù)

      _ = microService.Run()

      1

      查看etcd中http://localhost:8080/etcdkeeper/是否有該模塊的注冊信息

      3. 接入網(wǎng)關(guān)

      3.1 接入路由

      api-gateway/weblib/handlers

      //備忘錄服務(wù) authed.GET("tasks", handlers.GetTaskList) authed.POST("task", handlers.CreateTask) authed.GET("task/:id", handlers.GetTaskDetail) authed.DELETE("task/:id", handlers.DeleteTask) authed.PUT("task/:id", handlers.UpdateTask)

      1

      2

      3

      4

      5

      6

      3.2 編寫接口(創(chuàng)建備忘錄為例子)

      注意這是一個多用戶的備忘錄,所以我們要確保的是創(chuàng)建到該用戶的管理下的備忘錄中。

      所以我們就需要用到用戶的id,所以就從Authorization中取出來。

      func CreateTask(ginCtx *gin.Context) { var taskReq services.TaskRequest PanicIfTaskError(ginCtx.Bind(&taskReq)) //從gin.keys取出服務(wù)實例 claim,_ := util.ParseToken(ginCtx.GetHeader("Authorization")) taskReq.Uid = uint64(claim.Id) taskService := ginCtx.Keys["taskService"].(services.TaskService) taskRes, err := taskService.CreateTask(context.Background(), &taskReq) PanicIfTaskError(err) ginCtx.JSON(200, gin.H{"data": taskRes.TaskDetail}) }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      3.3 測試

      創(chuàng)建備忘錄

      展示用戶備忘錄

      修改備忘錄

      Go 微服務(wù)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:園林綠化工程項目進(jìn)度表(園林綠化工程項目進(jìn)度表模板)
      下一篇:如何在WPS中調(diào)整A4文件為A3標(biāo)準(zhǔn)試卷并打印?
      相關(guān)文章
      亚洲综合网站色欲色欲| 亚洲一区二区精品视频| 亚洲大尺度无码无码专区| 337p日本欧洲亚洲大胆人人 | 亚洲日韩欧洲乱码AV夜夜摸| 亚洲成?v人片天堂网无码| 精品国产亚洲AV麻豆| 亚洲6080yy久久无码产自国产| 亚洲一区二区三区高清在线观看| 亚洲成a人片在线不卡| 亚洲xxxxxx| 亚洲永久在线观看| 亚洲私人无码综合久久网| 亚洲日韩av无码中文| 亚洲精品第一国产综合亚AV| 在线观看亚洲AV日韩A∨| 亚洲人成电影网站色www| 亚洲精品无码少妇30P| 国产AV无码专区亚洲AV蜜芽| 国产亚洲视频在线| 2048亚洲精品国产| 亚洲中文字幕在线第六区| 亚洲毛片αv无线播放一区| 亚洲AV成人片色在线观看高潮| 久久久久亚洲精品无码蜜桃| 亚洲成A∨人片在线观看无码| 亚洲免费电影网站| 亚洲精品人成网线在线播放va| 成a人片亚洲日本久久| 亚洲综合亚洲综合网成人| 亚洲人JIZZ日本人| 亚洲欧洲日产国产综合网| 777亚洲精品乱码久久久久久| 1区1区3区4区产品亚洲| 亚洲AV综合色区无码二区爱AV| 亚洲人成77777在线观看网| 亚洲大码熟女在线观看| 亚洲A∨午夜成人片精品网站 | 狼人大香伊蕉国产WWW亚洲| 国产精品亚洲а∨天堂2021| 亚洲日韩中文在线精品第一 |