前言

最近有空学了 Golang,并动手写了个小项目,算是现学现用,主要是为了加深理解。由于刚入门,项目中可能会有一些错误或不够优化的地方,还请多多指教

项目介绍

目前在网上存在着很多公共壁纸API,但是大部分API的访问速度十分感人,尤其在高流量的情况下容易出现访问延迟或超时的情况。所以就打算自己实现一个,也借此机会提升对Golang的理解和应用。目前项目主要基于Golang语言实现,结合Gin框架处理HTTP请求,同时采用Redis作为缓存管理,结合OSS(对象存储服务)存储壁纸图片,以确保高效的图片存储与读取能力。在通过一系列的优化,提升了壁纸API的访问速度和稳定性,在高并发场景下依然能保持良好的响应性能。

项目特点

1、后端技术栈:

  • Golang:作为后端开发语言,Golang以其并发性、轻量级和高效性成为现代API开发的优选语言。本项目充分利用了Golang的高性能网络处理能力和内存管理,确保在大量请求下依然保持高效处理。
  • Gin框架:Gin是一个基于Golang的高性能Web框架,采用了路由器、JSON解析和中间件等功能,使得API请求处理非常高效且易于扩展。本项目通过Gin提供了灵活的路由设计,确保API的可维护性和扩展性。

2、高效的缓存机制:

  • Redis缓存:为了提升壁纸的读取速度并减少对OSS的频繁请求,本项目使用Redis作为缓存系统。Redis以其高效的内存存储特性,能够极大地减少数据的访问延迟,提供快速的数据读取和写入功能。壁纸数据存储在 Redis 的列表中,保证快速读取。
  • 随机壁纸缓存:为了实现壁纸的随机展示,系统采用了Redis的List数据结构来存储壁纸文件名,借助Redis的高效读取机制,通过先进后出确保每次请求都能快速获取到不同随机的壁纸,当对应标签的所有壁纸都获取一遍之后,会重置对应标签的缓存。

3、图片存储与管理:

  • OSS(对象存储服务):壁纸图片通过OSS进行存储,OSS提供了高可用、高性能的存储服务,适用于大规模图片的存储与管理。本项目通过与OSS的集成,能够高效地上传和读取壁纸资源,避免了本地存储的空间压力和管理复杂性,当然还需要配置一个CDN加速域名来访问。

4、API设计与功能:

  • 设备类型支持:API设计支持根据不同的设备类型(如PC、手机等)返回不同分辨率的壁纸,后续考虑在此基础上添加更多标签。
  • 上传壁纸功能:用户可以选择对应设备标签,单个或批量上传图片,同时同步更新到Redis缓存中。
  • 壁纸随机获取:通过调用API,用户可以获取到随机壁纸,系统会从Redis缓存中获取壁纸列表,并随机返回一张。同时在取缓存和自动刷新缓存时新增了Redis分布式锁,避免了在高并发情况下发生缓存竞争。

5、性能与稳定性优化:

  • 限流机制:为了避免高并发访问导致服务器压力过大,本项目实现了基于IP的请求限流功能。通过限制每秒的请求数,确保API的稳定性,避免因流量过大导致系统崩溃或响应延迟。

本站已使用该API,刷新页面即可显示实际效果,或者在美化设置中自行设置,如下所示。

img.png

项目部署

1、自行下载源码编译打包后自部署,需要如下前置条件以及相关环境:

自行修改./configs/config.yaml配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server:
port: ####

redis:
addr: "127.0.0.1:6379"
password: "" # Redis 密码,如果没有可以留空
db: 0
pool_size: 100
min_idle_conns: 20

cdn:
base_url: "####" # 你的OSS访问地址

oss:
endpoint: "" # OSS 区域 Endpoint
access_key_id: "" # Access Key ID
access_key_secret: "" # Access Key Secret
bucket: "" # OSS 存储桶名称

提前安装以下软件:

  • redis@latest
  • Go@1.20

设置Nginx代理,示例如下所示

1
2
3
4
5
location / {
......
proxy_pass http://127.0.0.1:6523/;
.....
}

2、通过Docker部署

新增docker-compose.yml配置文件,输入以下内容,####部分配置需要自行修改:

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
version: '3.8'

services:
# Redis 服务
redis:
image: redis:alpine # 使用官方的 Redis 镜像
container_name: redis
restart: always
ports:
- "6379:6379" # 映射 Redis 的端口到宿主机
volumes:
- ./data/redis:/data # 持久化 Redis 数据

# wallpaper-api 服务
wallpaper-api:
image: txm123/wallpaper-api:latest
container_name: wallpaper-api
restart: always
ports:
- "6523:6523" # 映射宿主机端口 6523 到容器内部端口
volumes:
- ./logs:/app/logs # 挂载日志文件目录
environment:
- GIN_MODE=release # 设定 Gin 运行环境
- SERVER_PORT=######## # 项目启动端口 同步修改容器内映射端口
- REDIS_ADDR=redis:6379 # 使用 Redis 服务的容器名作为 Redis 地址
- REDIS_PASSWORD=###### # Redis 默认没有密码
- REDIS_DB=0 # Redis 数据库的编号
- REDIS_POOL_SIZE=100 # 连接池的最大连接数
- REDIS_MIN_IDLE_CONNS=20 # 连接池中最小空闲连接数
- CDN_BASE_URL=######## # oss cdn 访问地址
- OSS_ENDPOINT=######## # OSS 区域 Endpoint
- OSS_ACCESS_KEY_ID=######## # Access Key ID
- OSS_ACCESS_KEY_SECRET=######## # Access Key Secret
- OSS_BUCKET=######## # OSS 存储桶名称
- LOG_FILE_PATH=##### # 日志文件路径(非必填,需同步修改wallpaper-api挂载日志目录)

然后输入以下命令拉取镜像启动即可

1
docker compose up -d

设置Nginx代理,示例如下所示

1
2
3
4
5
location / {
......
proxy_pass http://127.0.0.1:6523/;
......
}

3、通过GitHub action发布到Docker hub自行部署

参考

总结

其实还有很多功能想实现,但暂时没有时间,比如图片的增删查改等管理功能。当然这些都是后话,留待以后有时间再开发。目前系统还缺少一个监控图片上传功能,如果你用的是阿里云OSS的,可以配置阿里云函数计算写个脚本监控OSS上传图片的事件,调用刷新缓存的接口,这样就不需要手动刷新。但是这块我也不太熟悉。所以就没弄了,如果感兴趣的话可以搜索一下。