Browse Source

feat: now slave server can sync options with master server (close #88)

JustSong 2 years ago
parent
commit
2d39a135f2
3 changed files with 39 additions and 8 deletions
  1. 19 8
      README.md
  2. 7 0
      main.go
  3. 13 0
      model/option.go

+ 19 - 8
README.md

@@ -55,19 +55,20 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
    + [x] 自定义渠道:例如使用自行搭建的 OpenAI 代理
 2. 支持通过**负载均衡**的方式访问多个渠道。
 3. 支持 **stream 模式**,可以通过流式传输实现打字机效果。
-4. 支持**令牌管理**,设置令牌的过期时间和使用次数。
-5. 支持**兑换码管理**,支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
-6. 支持**通道管理**,批量创建通道。
-7. 支持发布公告,设置充值链接,设置新用户初始额度。
-8. 支持丰富的**自定义**设置,
+4. 支持**多机部署**,[详见此处](#多机部署)。
+5. 支持**令牌管理**,设置令牌的过期时间和使用次数。
+6. 支持**兑换码管理**,支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
+7. 支持**通道管理**,批量创建通道。
+8. 支持发布公告,设置充值链接,设置新用户初始额度。
+9. 支持丰富的**自定义**设置,
    1. 支持自定义系统名称,logo 以及页脚。
    2. 支持自定义首页和关于页面,可以选择使用 HTML & Markdown 代码进行自定义,或者使用一个单独的网页通过 iframe 嵌入。
-9. 支持通过系统访问令牌访问管理 API。
-10. 支持用户管理,支持**多种用户登录注册方式**:
+10. 支持通过系统访问令牌访问管理 API。
+11. 支持用户管理,支持**多种用户登录注册方式**:
     + 邮箱登录注册以及通过邮箱进行密码重置。
     + [GitHub 开放授权](https://github.com/settings/applications/new)。
     + 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
-11. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
+12. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
 
 ## 部署
 ### 基于 Docker 进行部署
@@ -133,6 +134,14 @@ sudo service nginx restart
 
 更加详细的部署教程[参见此处](https://iamazing.cn/page/how-to-deploy-a-website)。
 
+### 多机部署
+1. 所有服务器 `SESSION_SECRET` 设置一样的值。
+2. 必须设置 `SQL_DSN`,使用 MySQL 数据库而非 SQLite,请执行配置主备数据库同步。
+3. 所有从服务器必须设置 `SYNC_FREQUENCY`,以定期从数据库同步配置。
+4. 从服务器可以选择设置 `FRONTEND_BASE_URL`,以重定向页面请求到主服务器。‘
+
+环境变量的具体使用方法详见[此处](#环境变量)。
+
 ## 配置
 系统本身开箱即用。
 
@@ -159,6 +168,8 @@ sudo service nginx restart
    + 例子:`SQL_DSN=root:123456@tcp(localhost:3306)/one-api`
 4. `FRONTEND_BASE_URL`:设置之后将使用指定的前端地址,而非后端地址。
    + 例子:`FRONTEND_BASE_URL=https://openai.justsong.cn`
+5. `SYNC_FREQUENCY`:设置之后将定期与数据库同步配置,单位为秒,未设置则不进行同步。
+   + 例子:`SYNC_FREQUENCY=60`
 
 ### 命令行参数
 1. `--port <port_number>`: 指定服务器监听的端口号,默认为 `3000`。

+ 7 - 0
main.go

@@ -47,6 +47,13 @@ func main() {
 
 	// Initialize options
 	model.InitOptionMap()
+	if os.Getenv("SYNC_FREQUENCY") != "" {
+		frequency, err := strconv.Atoi(os.Getenv("SYNC_FREQUENCY"))
+		if err != nil {
+			common.FatalLog(err)
+		}
+		go model.SyncOptions(frequency)
+	}
 
 	// Initialize HTTP server
 	server := gin.Default()

+ 13 - 0
model/option.go

@@ -4,6 +4,7 @@ import (
 	"one-api/common"
 	"strconv"
 	"strings"
+	"time"
 )
 
 type Option struct {
@@ -59,6 +60,10 @@ func InitOptionMap() {
 	common.OptionMap["ModelRatio"] = common.ModelRatio2JSONString()
 	common.OptionMap["TopUpLink"] = common.TopUpLink
 	common.OptionMapRWMutex.Unlock()
+	loadOptionsFromDatabase()
+}
+
+func loadOptionsFromDatabase() {
 	options, _ := AllOption()
 	for _, option := range options {
 		err := updateOptionMap(option.Key, option.Value)
@@ -68,6 +73,14 @@ func InitOptionMap() {
 	}
 }
 
+func SyncOptions(frequency int) {
+	for {
+		time.Sleep(time.Duration(frequency) * time.Second)
+		common.SysLog("Syncing options from database")
+		loadOptionsFromDatabase()
+	}
+}
+
 func UpdateOption(key string, value string) error {
 	// Save to database first
 	option := Option{