
我非常推荐您阅读这篇名为《『学习笔记』Nginx 中的负载均衡配置与优化全面指南》
链接:https://cloud.tencent.com/developer/article/2470754)
该博客由腾讯云开发者社区的作者数字扫地僧精心撰写,内容全面且深入,详细讲解了Nginx中负载均衡的配置与优化方法。从负载均衡的基本概念到Nginx的负载均衡核心功能,再到具体的配置示例和性能调优建议,作者都进行了清晰的阐述。此外,博客还提供了丰富的示例代码和实用的优化技巧,帮助您更好地理解和应用Nginx的负载均衡功能。无论您是初学者还是有一定经验的开发者,都能从这篇博客中受益匪浅。
之前我们通过了三篇文章实现了Go二维码小游戏的设计、开发、部署和监控,实现一个产品或项目很容易,但是优雅的实现却不太容易。对于我们研发小伙伴来说,优雅的代码是提高产品性能和减少技术债务的必要途径,所以我们将再用一篇文章来进行复盘,看看目前的项目还有哪些需要优化的地方,下面我们开始~
1)功能优化
在我们项目的运行过程中,用户来请求时会不断的生成静态资源文件到我们的本地,如果没有这些文件的清理机制,我们的存储压力就会越来越大,因此需要有一个资源的主动或被动清理机制来确保我们可以及时的释放存储资源。
2)Docker镜像优化
在我们下篇中有打包Docker镜像的过程,但是如果有注意到的小伙伴就会知道,在我们使用Dockerfile打包镜像后得到的Docker镜像竟然有1.1G,显然这个镜像的大小超过了我们理想的情况,所以在Docker镜像打包的方向还有优化。
3)编码优化
虽然我们整个项目现有的代码不是很多,但是也存在一些优化空间和查漏补缺的地方,比如还没有Makefile等等,这些东西都需要补充和优化。
然后我们来一起进行各个模块的细节优化
文件清理脚本的目的就是通过一行命令来达到我们的文件清理目的,主要是通过Go的flag机制进行,下面是代码:
1)首先定义一个参数,在执行main函数时作为输入参数:
const (
ExecStart = 0
ExecClean = 1
)
var exec int
func init() {
flag.IntVar(&exec, "exec", 0, "0: start server; 1: clean file")
flag.Parse()
}2)然后我们改写main.go中的main函数
func main() {
InitConfig()
switch exec {
case ExecStart:
log.Infof("starting server config: %+v", GetGlobalConfig())
_ = os.Mkdir(fmt.Sprintf(".%s/", GetGlobalConfig().TmpPath), os.ModePerm)
go CleanTask()
runHttp()
case ExecClean:
if err := CleanTmpFile(GetGlobalConfig().TmpPath); err != nil {
log.Errorf("clean tmp file err:%s", err)
}
default:
fmt.Println("err")
}
}3)具体的文件清理逻辑:
func CleanTmpFile(dir string) error {
log.Infof("clean path:%s", dir)
// 打开目录
dir = fmt.Sprintf(".%s", dir)
d, err := os.Open(dir)
if err != nil {
log.Errorf("open dir err:%s", err)
return err
}
defer func() {
_ = d.Close()
}()
// 读取目录中的文件和子目录
entries, err := d.Readdir(-1)
if err != nil {
log.Errorf("read dir err:%s", err)
return err
}
for _, entry := range entries {
// 构建完整路径
path := filepath.Join(dir, entry.Name())
// 如果是文件,则删除
if !entry.IsDir() {
if err := os.Remove(path); err != nil {
log.Errorf("remove file err:%s", err)
return err
}
log.Infof("delete file:%s", path)
} else {
log.Infof("skip dir: %s", path)
}
}
return nil
}然后我们在启动项目时就可以进行命令行启动:
# 正常启动服务
go run main.go
# 进行文件清理
go run main.go -exec 1合理使用定时任务在Go项目中可以显著提升系统的自动化水平和运维效率,通过精确控制任务执行时间,实现定期的数据备份、日志清理、状态检查等维护操作,确保系统稳定运行并减少人工干预。
在本项目中就是定时器+文件清理脚本,比如:
func CleanTask() {
c := cron.New()
_, err := c.AddFunc("* * * * * *", func() {
// TODO 文件清理脚本
})
if err != nil {
fmt.Println("Error adding task:", err)
return
}
c.Start()
}然后我们就可以在main函数中启动一个Goruntine来启动定时任务:
go CleanTask()Docker镜像的优化方向主要集中在以下几个方面:
1)精简基础镜像:选择体积较小、更新频率较低的基础镜像,如Alpine Linux,以减少镜像拉取和构建的时间,并降低最终镜像的大小。
2)减少镜像层级:在Dockerfile中,尽量减少层的数量。通过合并多个命令来减少层数,可以提高构建速度并减小镜像体积。例如,可以使用&&符号将多个命令连接在一起执行,以减少镜像层的数量。
3)按需安装软件:仅安装运行应用所必需的软件包,避免安装多余的工具和库。这可以进一步减小镜像的大小,并降低潜在的安全风险。
# 使用最新的Ubuntu作为基础镜像
FROM ubuntu:latest
# 设置工作目录
WORKDIR /app
# 将Go代码复制到容器中
COPY . /app
# 设置容器启动时执行的命令
ENTRYPOINT ["/app/QR-code-go"]这样做的最大好处就是能将Docker镜像大小减小到原有的十分之一,但不好的地方就是需要将编译操作放在本地来执行,这样做就会导致必须要保持本地和Docker镜像是同一CPU指令集。
Makefile在Go项目中扮演着自动化构建脚本的角色,它通过定义构建规则和目标,简化了编译、打包、测试等任务的执行过程,提高了开发效率,同时支持跨平台构建,确保了项目在不同操作系统上的一致性,并以其结构化的语法增强了项目的可读性和可维护性。
下面我们编写本项目的Makefile:
# 定义Go编译器和构建标志
GOCMD=go
GOBUILD=$(GOCMD) build -o myapp .
# 定义Docker相关变量
IMAGE_NAME=my-go-app
DOCKERFILE=Dockerfile
# 编译Go项目
build:
$(GOBUILD)
# 清理构建的文件(可选)
clean:
$(GOCMD) clean -i -cache -modcache
rm -f myapp
# 构建Docker镜像
image:
docker build -t $(IMAGE_NAME) -f $(DOCKERFILE) .
# 运行Docker容器(仅用于测试,可选)
run:
docker run --rm -it -p 8080:8080 $(IMAGE_NAME)
# 完整的构建和打包流程(包含编译和打包Docker镜像)
all: clean build imageMakefile使用方式:
# 编译项目
make
# 构建Docker镜像
make image简单说一下这方面的优化,就是尽量将独立功能的代码放在一个文件里,比如我们当前的代码HTTP的处理方法和main函数都是放在main.go文件中,这种情况一旦HTTP的处理方法越来越多,就会导致main函数所在的文件非常冗余,因此需要将HTTP业务代码单独放置在一个文件中,这样代码结构会比较清晰。
在这篇文章中我们通过功能优化、Docker镜像优化和编码优化三个方向来进行整个项目的补充和优化,当然完成这些之后并不意味着项目就达到了完美的程度,还有很多地方需要进行完善和优化,在这里也希望读者朋友能给出建议。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。