PeaceSheep's blog PeaceSheep's blog
首页
  • 分类
  • 标签
  • 归档
相关链接
提建议&咨询&赞赏
GitHub (opens new window)

PeaceSheep

以最简洁、易懂的话解决问题
首页
  • 分类
  • 标签
  • 归档
相关链接
提建议&咨询&赞赏
GitHub (opens new window)
  • 下载器

  • 作业网站管理

  • 联邦学习

  • 随手写的小项目

  • docker

  • 即时通讯

    • 想自己写一个高性能的IM
    • 自己实现高性能IM-服务划分
    • 自己实现高性能IM-初始代码框架搭建并实现依赖注入
      • RPC服务-kitex 项目搭建
      • HTTP 服务-hertz项目搭建
      • 依赖注入改造
    • kitex 与 hertz 配合使用,实现服务发现链路追踪等功能
  • 项目
  • 即时通讯
PeaceSheep
2024-10-20
目录

自己实现高性能IM-初始代码框架搭建并实现依赖注入

本文介绍了基本的kitex项目搭建,实现了log 的使用,使用依赖注入实现控制反转。需要注意的是,在windows上可能会出现问题,推荐在linux或mac开发。

项目主要使用了字节跳动的RPC框架kitex (opens new window)。

# RPC服务-kitex 项目搭建

git clone https://github.com/cloudwego/kitex-examples.git
1

把这个项目克隆下来,然后单独把hello拿出来,其他的删掉。使用go mod tidy同步一下依赖,如果没有go.mod就先go mod init xx一下。

可以运行一下当前软件包,也就是服务端,然后再运行一下client里面的main.go这个单个文件,如果看到client不断输出response就说明成功了。

如果要实现自己的服务,只需要在thrift 文件中,定义自己的Req 结构体、Resp 结构体以及对应的服务函数即可。例如,编辑idl/auth.thrift:

namespace go auth

include "base.thrift"

struct LoginReq {
    1: required string username
    2: required string password
}

struct LoginResp {
    1: required base.BaseResp baseResp
    2: optional string token
}



service AuthService {
    LoginResp Login(LoginReq req)

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

然后运行kitex -module github.com/li1553770945/sheepim-auth-service -service sheepim-auth-service idl/auth.thrift就可以生成服务端和客户端对应的代码了。

# HTTP 服务-hertz项目搭建

# 依赖注入改造

主要使用wire (opens new window)库实现,这里不在介绍安装方法。

所谓依赖注入,就是如果A需要B,则创建A的时候应该传入一个B的对象,而不是由A自己新建B的对象或者使用全局的B对象。

以下只是我习惯的写法,不一定对每个人都适用。

首先,新建一个container.go文件新建container类,然后把handler里面需要的都写成它的属性,比如一般kitex项目有个handler,handler里面我们需要调用自己的service,就可以把service的接口声明成container的属性。如果是service需要而其他地方不需要一般不需要写在container里面。

container是一个最顶层的类,我们可以把它的对象命名为APP,并且得到它需要使用单例模式,也就是说我们整个项目有且仅有一个container对象,并且整个项目只有这一个全局变量。

package container

import (
	"github.com/li1553770945/sheepim-user-service/biz/infra/config"
	"github.com/li1553770945/sheepim-user-service/biz/internal/service"
	"sync"
)

type Container struct {
	Config      *config.Config
	UserService user.IUserService
}

var APP *Container
var once sync.Once // 通过once实现单例模式

func GetGlobalContainer() *Container {
	if APP == nil {
		panic("APP在使用前未初始化")
	}
	return APP
}

func InitGlobalContainer(config *config.Config) {
	once.Do(func() {
		APP = GetContainer(config)
	})
}
func NewContainer(config *config.Config, userService user.IUserService,
) *Container {
	return &Container{
		Config:      config,
		UserService: userService,
	}

}

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

然后新建一个wire.go实现一个GetContainer函数:

//go:build wireinject
// +build wireinject

package container

import (
	"github.com/google/wire"
	"github.com/li1553770945/sheepim-user-service/biz/infra/config"
	"github.com/li1553770945/sheepim-user-service/biz/infra/database"
	"github.com/li1553770945/sheepim-user-service/biz/internal/repo"
	"github.com/li1553770945/sheepim-user-service/biz/internal/service"
)

func GetContainer(env string) *Container {
	panic(wire.Build(

		//infra
    config.NewConfig

		//repo
		repo.NewRepository,
		database.NewDatabase,

		//service
		user.NewUserService,

		NewContainer,
	))
}
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

把所有的类的新建对象的函数写在这里,然后在这个目录下运行wire命令。就会得到一个wire_gen.go,里面是生成的代码。

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package container

import (
	"github.com/li1553770945/sheepim-user-service/biz/infra/config"
	"github.com/li1553770945/sheepim-user-service/biz/infra/database"
	"github.com/li1553770945/sheepim-user-service/biz/internal/repo"
	"github.com/li1553770945/sheepim-user-service/biz/internal/service"
)

// Injectors from wire.go:

func GetContainer(env string) *Container {
  cfg := config.NewConfig(env)
	db := database.NewDatabase(cfg)
	iRepository := repo.NewRepository(db)
	iUserService := user.NewUserService(iRepository)
	container := NewContainer(cfg, iUserService)
	return container
}

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

我们在main里面调用InitGlobalContainer就会初始化所有需要初始化的对象,handler里面就可以用GetGlobalContainer得到全局的container,从而使用service了。

编辑 (opens new window)
上次更新: 2025/04/15, 10:52:45
自己实现高性能IM-服务划分
kitex 与 hertz 配合使用,实现服务发现链路追踪等功能

← 自己实现高性能IM-服务划分 kitex 与 hertz 配合使用,实现服务发现链路追踪等功能→

最近更新
01
ubuntu安装g++显示已有但是输入g++又找不到命令
04-15
02
使用cloudflare-r2搭建webdav
04-08
03
LLM聚合平台客户端对比
03-29
更多文章>
Theme by Vdoing | Copyright © 2022-2025 PeaceSheep
冀ICP备2022004632号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式