feat: metona-search-proxy v2.1 — CLI管理(start/stop/status/restart)+PID文件+端口占用检测+两种部署方式
This commit is contained in:
+114
-119
@@ -24,38 +24,23 @@ sudo apt update && sudo apt install -y golang-go
|
|||||||
|
|
||||||
# CentOS/RHEL
|
# CentOS/RHEL
|
||||||
sudo yum install -y golang
|
sudo yum install -y golang
|
||||||
|
|
||||||
# 或手动安装最新版
|
|
||||||
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
|
|
||||||
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
|
|
||||||
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc && source ~/.bashrc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 安装与编译
|
## 编译
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 克隆仓库
|
|
||||||
cd /opt
|
cd /opt
|
||||||
git clone https://gitee.com/thzxx/metona-ollama-desktop.git
|
git clone https://gitee.com/thzxx/metona-ollama-desktop.git
|
||||||
cd metona-ollama-desktop/search-proxy
|
cd metona-ollama-desktop/search-proxy
|
||||||
|
|
||||||
# 2. 编译
|
|
||||||
go build -o metona-search-proxy .
|
go build -o metona-search-proxy .
|
||||||
|
|
||||||
# 3. 验证
|
|
||||||
./metona-search-proxy --version
|
|
||||||
# metona-search-proxy v2.0.0 go/go1.22.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 本地交叉编译(在本地编译好上传)
|
### 本地交叉编译(编译好再上传)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Windows 上编译 Linux 版本
|
# 编译 Linux 版本
|
||||||
GOOS=linux GOARCH=amd64 go build -o metona-search-proxy .
|
|
||||||
|
|
||||||
# macOS 上编译 Linux 版本
|
|
||||||
GOOS=linux GOARCH=amd64 go build -o metona-search-proxy .
|
GOOS=linux GOARCH=amd64 go build -o metona-search-proxy .
|
||||||
|
|
||||||
# 上传到服务器
|
# 上传到服务器
|
||||||
@@ -64,10 +49,37 @@ scp metona-search-proxy user@your-server:/opt/metona-search-proxy/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CLI 命令
|
## 全局命令
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./metona-search-proxy [选项]
|
sudo cp metona-search-proxy /usr/local/bin/
|
||||||
|
sudo chmod +x /usr/local/bin/metona-search-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
之后任何目录都可以直接用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
metona-search-proxy --version
|
||||||
|
metona-search-proxy -status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CLI 命令
|
||||||
|
|
||||||
|
### 服务管理
|
||||||
|
|
||||||
|
```bash
|
||||||
|
metona-search-proxy -start # 后台启动
|
||||||
|
metona-search-proxy -stop # 停止
|
||||||
|
metona-search-proxy -status # 查看状态
|
||||||
|
metona-search-proxy -restart # 重启
|
||||||
|
```
|
||||||
|
|
||||||
|
### 运行参数
|
||||||
|
|
||||||
|
```bash
|
||||||
|
metona-search-proxy [选项]
|
||||||
|
|
||||||
选项:
|
选项:
|
||||||
-port int 监听端口 (默认 7899)
|
-port int 监听端口 (默认 7899)
|
||||||
@@ -76,128 +88,111 @@ scp metona-search-proxy user@your-server:/opt/metona-search-proxy/
|
|||||||
-burst int 限流突发容量 (默认 60)
|
-burst int 限流突发容量 (默认 60)
|
||||||
-timeout int 搜索引擎超时/秒 (默认 12)
|
-timeout int 搜索引擎超时/秒 (默认 12)
|
||||||
-version 显示版本号
|
-version 显示版本号
|
||||||
|
-start 后台启动
|
||||||
示例:
|
-stop 停止后台实例
|
||||||
./metona-search-proxy # 默认配置
|
-status 查看运行状态
|
||||||
./metona-search-proxy -port 7899 -cache 10 # 自定义端口和缓存
|
-restart 重启后台实例
|
||||||
./metona-search-proxy -port 7899 -rate 50 -burst 100 # 高并发配置
|
|
||||||
PORT=7899 ./metona-search-proxy # 也可用环境变量
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看状态
|
||||||
|
metona-search-proxy -status
|
||||||
|
# ● 运行中 PID: 12345 端口: 7899
|
||||||
|
# 健康检查: http://localhost:7899/health
|
||||||
|
|
||||||
|
# 前台运行(调试用,Ctrl+C 停止)
|
||||||
|
metona-search-proxy
|
||||||
|
|
||||||
|
# 后台启动
|
||||||
|
metona-search-proxy -start
|
||||||
|
# 已后台启动 (PID: 12345)
|
||||||
|
|
||||||
|
# 停止
|
||||||
|
metona-search-proxy -stop
|
||||||
|
# 已停止 (PID: 12345)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 部署方式(二选一)
|
||||||
|
|
||||||
|
### 方式一:systemd 服务(推荐—生产环境)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 安装二进制
|
||||||
|
sudo mkdir -p /opt/metona-search-proxy
|
||||||
|
sudo cp metona-search-proxy /opt/metona-search-proxy/
|
||||||
|
sudo chmod +x /opt/metona-search-proxy/metona-search-proxy
|
||||||
|
|
||||||
|
# 2. 创建服务
|
||||||
|
sudo cp metona-search-proxy.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now metona-search-proxy
|
||||||
|
|
||||||
|
# 3. 管理
|
||||||
|
sudo systemctl status metona-search-proxy # 状态
|
||||||
|
sudo systemctl stop metona-search-proxy # 停止
|
||||||
|
sudo journalctl -u metona-search-proxy -f # 日志
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 使用 systemd 后不要再用 `-start/-stop` CLI 命令,会冲突。
|
||||||
|
|
||||||
|
### 方式二:CLI 管理(轻量—个人开发)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装全局命令
|
||||||
|
sudo cp metona-search-proxy /usr/local/bin/
|
||||||
|
|
||||||
|
# 启动
|
||||||
|
metona-search-proxy -start
|
||||||
|
|
||||||
|
# 查看状态
|
||||||
|
metona-search-proxy -status
|
||||||
|
|
||||||
|
# 停止
|
||||||
|
metona-search-proxy -stop
|
||||||
|
|
||||||
|
# 设置开机自启(加到 crontab)
|
||||||
|
(crontab -l 2>/dev/null; echo "@reboot metona-search-proxy -start") | crontab -
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 使用 CLI 管理前确保 systemd 服务已停止:`sudo systemctl stop metona-search-proxy`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 测试
|
## 测试
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 启动
|
|
||||||
./metona-search-proxy &
|
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
curl http://localhost:7899/health
|
curl http://localhost:7899/health
|
||||||
|
curl "http://localhost:7899/search?q=hello&engine=google&n=5"
|
||||||
# 单引擎搜索
|
curl "http://localhost:7899/search?q=天气&engine=all&n=10"
|
||||||
curl "http://localhost:7899/search?q=hello+world&engine=google&n=5"
|
|
||||||
|
|
||||||
# 四引擎并行
|
|
||||||
curl "http://localhost:7899/search?q=今天天气&engine=all&n=10"
|
|
||||||
|
|
||||||
# 百度搜索
|
|
||||||
curl "http://localhost:7899/search?q=春节&engine=baidu&n=5"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 响应格式
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"query": "hello world",
|
|
||||||
"engine": "google",
|
|
||||||
"total": 5,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"title": "...",
|
|
||||||
"url": "https://...",
|
|
||||||
"snippet": "...",
|
|
||||||
"engine": "google"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 安装为系统服务(开机自启)
|
## API
|
||||||
|
|
||||||
### 1. 拷贝二进制文件
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/metona-search-proxy
|
|
||||||
sudo cp metona-search-proxy /opt/metona-search-proxy/
|
|
||||||
sudo chmod +x /opt/metona-search-proxy/metona-search-proxy
|
|
||||||
```
|
```
|
||||||
|
GET /search?q=关键词&engine=all&n=10
|
||||||
|
|
||||||
### 2. 创建 systemd 服务文件
|
engine: google | bing | ddg | baidu | all (默认)
|
||||||
|
n: 1-20,默认10
|
||||||
|
缓存: 5分钟(可配)
|
||||||
|
限流: 30 req/s(可配)
|
||||||
|
|
||||||
```bash
|
GET /health
|
||||||
sudo tee /etc/systemd/system/metona-search-proxy.service << 'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=Metona Search Proxy - Google/Bing/DDG/Baidu API
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/opt/metona-search-proxy/metona-search-proxy
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
Environment=PORT=7899
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 启动服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable metona-search-proxy # 开机自启
|
|
||||||
sudo systemctl start metona-search-proxy # 立即启动
|
|
||||||
|
|
||||||
# 查看状态
|
|
||||||
sudo systemctl status metona-search-proxy
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
sudo journalctl -u metona-search-proxy -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 验证
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:7899/health
|
|
||||||
# {"engines":["google","bing","ddg","baidu","all"],"status":"ok","time":"...","version":"2.0.0"}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 本应用配置
|
## 本应用配置
|
||||||
|
|
||||||
Metona Ollama Desktop 设置面板 → 代理设置 → 填入:
|
Metona Ollama Desktop → 设置 → 代理 → 填入:
|
||||||
|
|
||||||
```
|
```
|
||||||
http://你的服务器IP:7899
|
http://服务器IP:7899
|
||||||
```
|
```
|
||||||
|
|
||||||
重启应用即可。web_search 的 Google/DDG/Bing/百度 四引擎请求会自动路由到这台服务器。
|
重启应用即可。
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 常用管理命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl start metona-search-proxy # 启动
|
|
||||||
sudo systemctl stop metona-search-proxy # 停止
|
|
||||||
sudo systemctl restart metona-search-proxy # 重启
|
|
||||||
sudo systemctl status metona-search-proxy # 状态
|
|
||||||
sudo journalctl -u metona-search-proxy -f # 实时日志
|
|
||||||
sudo journalctl -u metona-search-proxy --since today # 今日日志
|
|
||||||
```
|
|
||||||
|
|||||||
+166
-6
@@ -7,12 +7,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -20,7 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "2.0.0"
|
const version = "2.1.0"
|
||||||
|
|
||||||
// ── CLI ──
|
// ── CLI ──
|
||||||
var (
|
var (
|
||||||
@@ -30,8 +33,14 @@ var (
|
|||||||
cliBurst = flag.Int("burst", 60, "限流突发容量")
|
cliBurst = flag.Int("burst", 60, "限流突发容量")
|
||||||
cliTimeout = flag.Int("timeout", 12, "搜索引擎请求超时(秒)")
|
cliTimeout = flag.Int("timeout", 12, "搜索引擎请求超时(秒)")
|
||||||
cliVersion = flag.Bool("version", false, "显示版本")
|
cliVersion = flag.Bool("version", false, "显示版本")
|
||||||
|
cliStop = flag.Bool("stop", false, "停止后台运行的实例")
|
||||||
|
cliStart = flag.Bool("start", false, "后台启动(nohup模式)")
|
||||||
|
cliStatus = flag.Bool("status", false, "查看运行状态")
|
||||||
|
cliRestart = flag.Bool("restart", false, "重启后台实例")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var pidFile = "/tmp/metona-search-proxy.pid"
|
||||||
|
|
||||||
// ── 限流器 ──
|
// ── 限流器 ──
|
||||||
type RateLimiter struct {
|
type RateLimiter struct {
|
||||||
tokens atomic.Int64
|
tokens atomic.Int64
|
||||||
@@ -76,8 +85,8 @@ func (rl *RateLimiter) Allow() bool {
|
|||||||
var cache sync.Map
|
var cache sync.Map
|
||||||
|
|
||||||
type cacheEntry struct {
|
type cacheEntry struct {
|
||||||
Results []Result `json:"-"`
|
Results []Result
|
||||||
ExpiresAt int64 `json:"-"`
|
ExpiresAt int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
@@ -106,7 +115,131 @@ var (
|
|||||||
cacheTTL int64
|
cacheTTL int64
|
||||||
)
|
)
|
||||||
|
|
||||||
// ── recovery middleware ──
|
// ── PID 管理 ──
|
||||||
|
|
||||||
|
func writePID(port int) {
|
||||||
|
pid := os.Getpid()
|
||||||
|
os.WriteFile(pidFile, []byte(fmt.Sprintf("%d\n%d", pid, port)), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readPID() (pid int, port int, ok bool) {
|
||||||
|
data, err := os.ReadFile(pidFile)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
pid, _ = strconv.Atoi(parts[0])
|
||||||
|
port, _ = strconv.Atoi(parts[1])
|
||||||
|
if pid < 1 || port < 1 {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
// 检查进程是否存在
|
||||||
|
proc, err := os.FindProcess(pid)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return pid, port, true
|
||||||
|
}
|
||||||
|
err = proc.Signal(syscall.Signal(0))
|
||||||
|
return pid, port, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopProcess(pid int) bool {
|
||||||
|
proc, err := os.FindProcess(pid)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return proc.Kill() == nil
|
||||||
|
}
|
||||||
|
err = proc.Signal(syscall.SIGTERM)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 等待进程退出
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
if err := proc.Signal(syscall.Signal(0)); err != nil {
|
||||||
|
os.Remove(pidFile)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
// force kill
|
||||||
|
proc.Signal(syscall.SIGKILL)
|
||||||
|
os.Remove(pidFile)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPort(port int) bool {
|
||||||
|
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
|
if err != nil {
|
||||||
|
return true // 端口已被占用 = 服务在运行
|
||||||
|
}
|
||||||
|
ln.Close()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func doStart() {
|
||||||
|
if pid, _, ok := readPID(); ok {
|
||||||
|
fmt.Printf("已在运行 (PID: %d)\n", pid)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if checkPort(*cliPort) {
|
||||||
|
fmt.Printf("端口 %d 已被占用\n", *cliPort)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
// 后台启动自己
|
||||||
|
args := []string{}
|
||||||
|
for _, a := range os.Args[1:] {
|
||||||
|
if a != "-start" && a != "--start" {
|
||||||
|
args = append(args, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd := exec.Command(os.Args[0], args...)
|
||||||
|
cmd.Stdout = nil
|
||||||
|
cmd.Stderr = nil
|
||||||
|
cmd.Start()
|
||||||
|
fmt.Printf("已后台启动 (PID: %d)\n", cmd.Process.Pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doStop() {
|
||||||
|
pid, _, ok := readPID()
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("未找到运行中的实例")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if stopProcess(pid) {
|
||||||
|
fmt.Printf("已停止 (PID: %d)\n", pid)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("停止失败 (PID: %d)\n", pid)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doStatus() {
|
||||||
|
if pid, port, ok := readPID(); ok && checkPort(port) {
|
||||||
|
fmt.Printf("● 运行中 PID: %d 端口: %d\n", pid, port)
|
||||||
|
fmt.Printf(" 健康检查: http://localhost:%d/health\n", port)
|
||||||
|
fmt.Printf(" PID 文件: %s\n", pidFile)
|
||||||
|
} else {
|
||||||
|
fmt.Println("○ 未运行")
|
||||||
|
os.Remove(pidFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doRestart() {
|
||||||
|
if pid, _, ok := readPID(); ok {
|
||||||
|
stopProcess(pid)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
doStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── recovery 中间件 ──
|
||||||
func recoverWrap(h http.HandlerFunc) http.HandlerFunc {
|
func recoverWrap(h http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -388,7 +521,7 @@ func handleHealth(w http.ResponseWriter, r *http.Request) {
|
|||||||
"status": "ok",
|
"status": "ok",
|
||||||
"version": version,
|
"version": version,
|
||||||
"engines": []string{"google", "bing", "ddg", "baidu", "all"},
|
"engines": []string{"google", "bing", "ddg", "baidu", "all"},
|
||||||
"time": time.Now().UTC().Format(time.RFC3339),
|
"uptime": time.Now().UTC().Format(time.RFC3339),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,20 +532,44 @@ func writeJSON(w http.ResponseWriter, status int, v interface{}) {
|
|||||||
json.NewEncoder(w).Encode(v)
|
json.NewEncoder(w).Encode(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── main ──
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
// 管理命令(不需要启动服务)
|
||||||
if *cliVersion {
|
if *cliVersion {
|
||||||
fmt.Printf("metona-search-proxy v%s go/%s\n", version, runtime.Version())
|
fmt.Printf("metona-search-proxy v%s go/%s\n", version, runtime.Version())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if *cliStop {
|
||||||
|
doStop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if *cliStatus {
|
||||||
|
doStatus()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if *cliStart {
|
||||||
|
doStart()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if *cliRestart {
|
||||||
|
doRestart()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
port := os.Getenv("PORT")
|
||||||
if port == "" {
|
if port == "" {
|
||||||
port = fmt.Sprintf("%d", *cliPort)
|
port = fmt.Sprintf("%d", *cliPort)
|
||||||
}
|
}
|
||||||
|
portNum, _ := strconv.Atoi(port)
|
||||||
|
|
||||||
|
// 检查端口是否已被占用
|
||||||
|
if checkPort(portNum) {
|
||||||
|
log.Fatalf("端口 %s 已被占用。使用 metona-search-proxy -status 查看状态,或用 -restart 重启。", port)
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化
|
|
||||||
httpClient = &http.Client{
|
httpClient = &http.Client{
|
||||||
Timeout: time.Duration(*cliTimeout) * time.Second,
|
Timeout: time.Duration(*cliTimeout) * time.Second,
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
@@ -424,6 +581,9 @@ func main() {
|
|||||||
limiter = newRateLimiter(int64(*cliRate), int64(*cliBurst))
|
limiter = newRateLimiter(int64(*cliRate), int64(*cliBurst))
|
||||||
cacheTTL = int64(*cliCache)
|
cacheTTL = int64(*cliCache)
|
||||||
|
|
||||||
|
writePID(portNum)
|
||||||
|
defer os.Remove(pidFile)
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/search", recoverWrap(handleSearch))
|
mux.HandleFunc("/search", recoverWrap(handleSearch))
|
||||||
mux.HandleFunc("/health", recoverWrap(handleHealth))
|
mux.HandleFunc("/health", recoverWrap(handleHealth))
|
||||||
|
|||||||
Reference in New Issue
Block a user