feat: 添加aktools服务并更新架构文档

- 在data-service中添加aktools依赖和运行配置
- 更新Traefik配置添加压缩中间件
- 修改Consul配置启用ACL
- 更新README添加架构图和开发指南
- 添加架构图文档
This commit is contained in:
fanfpy 2025-06-21 22:53:09 +08:00
parent c2026d0a7b
commit 806e444297
9 changed files with 118 additions and 15 deletions

View File

@ -14,7 +14,47 @@
## 使用方式 ## 使用方式
```bash ```bash
docker-compose up --build docker compose up --build
``` ```
## 📦 技术架构
![架构图](docs/architecture.svg)
**核心组件**
- 服务发现Consul
- API网关Traefik with Let's Encrypt
- 消息队列RabbitMQ
- 数据存储PostgreSQL + Redis
**通信协议**
- RESTful API80% 服务)
- gRPCquant-service 与 data-service
## 🔧 环境变量
```env
CONSUL_HTTP_ADDR=consul:8500
ALPHAVANTAGE_API_KEY=your_key
```
## 📚 API 文档
访问统一入口:`http://localhost/docs`
## 🛠 开发指南
```bash
# Python 服务
pip install -r requirements.txt
uvicorn app:app --reload
# C# 服务
dotnet run
```
## 🤝 贡献规范
1. 分支命名feat/xxx, fix/xxx
2. 提交信息遵循 Conventional Commits
3. 提交 PR 前需通过 SonarQube 检测
## 📄 许可
[MIT](LICENSE)
访问入口:`http://localhost` 或你的服务器域名(如 AriStockAI.com 访问入口:`http://localhost` 或你的服务器域名(如 AriStockAI.com

View File

@ -1,5 +1,8 @@
datacenter = "dc1" ui_config {
data_dir = "/consul/data" enabled = true
server = true }
bootstrap_expect = 1
ui = true acl {
enabled = true
default_policy = "deny"
}

49
docs/architecture.drawio Normal file
View File

@ -0,0 +1,49 @@
<mxfile>
<diagram name="完整架构">
<mxGraphModel>
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<!-- 基础设施层 -->
<mxCell id="infra" value="基础设施层" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="50" y="20" width="700" height="120" as="geometry" />
</mxCell>
<!-- 微服务集群 -->
<mxCell id="services" value="微服务集群" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="100" y="180" width="600" height="300" as="geometry" />
</mxCell>
<!-- 具体服务 -->
<mxCell id="data" value="📊 数据服务(Python)" style="rounded=1;whiteSpace=wrap;html=1;" parent="services" vertex="1">
<mxGeometry x="20" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="quant" value="🧮 量化服务(Python)" style="rounded=1;whiteSpace=wrap;html=1;" parent="services" vertex="1">
<mxGeometry x="180" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="emotion" value="😀 情绪分析(Python)" style="rounded=1;whiteSpace=wrap;html=1;" parent="services" vertex="1">
<mxGeometry x="340" y="40" width="120" height="60" as="geometry" />
</mxCell>
<!-- C# 服务 -->
<mxCell id="recommend" value="⭐ 推荐服务(C#)" style="rounded=1;whiteSpace=wrap;html=1;" parent="services" vertex="1">
<mxGeometry x="20" y="140" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="user" value="👤 用户服务(C#)" style="rounded=1;whiteSpace=wrap;html=1;" parent="services" vertex="1">
<mxGeometry x="180" y="140" width="120" height="60" as="geometry" />
</mxCell>
<!-- 前端服务 -->
<mxCell id="frontend" value="🖥️ 前端界面(Vue.js)" style="rounded=1;whiteSpace=wrap;html=1;" parent="infra" vertex="1">
<mxGeometry x="300" y="40" width="120" height="60" as="geometry" />
</mxCell>
<!-- 连接关系 -->
<mxCell id="conn1" style="edgeStyle=orthogonalEdgeStyle;curved=1;" parent="1" source="frontend" target="user">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

4
docs/architecture.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 246 KiB

View File

@ -4,4 +4,4 @@ WORKDIR /app
COPY requirements.txt . COPY requirements.txt .
RUN pip install -r requirements.txt RUN pip install -r requirements.txt
COPY . . COPY . .
CMD ["python", "app.py"] CMD ["sh", "-c", "aktools run --port 8001 & python register.py && wait"]

View File

@ -1,5 +1,6 @@
from flask import Flask, jsonify from flask import Flask, jsonify
import threading import threading
import subprocess
from register import register_to_consul from register import register_to_consul
app = Flask(__name__) app = Flask(__name__)
@ -14,4 +15,5 @@ def hello():
if __name__ == "__main__": if __name__ == "__main__":
threading.Thread(target=register_to_consul).start() threading.Thread(target=register_to_consul).start()
subprocess.Popen(["aktools", "run", "--port", "8001"])
app.run(host="0.0.0.0", port=8000) app.run(host="0.0.0.0", port=8000)

View File

@ -3,8 +3,8 @@ import requests
def register_to_consul(): def register_to_consul():
time.sleep(3) # 等待服务稳定再注册 time.sleep(3) # 等待服务稳定再注册
service_name = "data-service" # 替换为 quant-service/emotion-service 等 service_name = "aktools-service" # AKTools 主服务
port = 8000 # 替换为 8001, 8002 等 port = 8001 # AKTools 端口
payload = { payload = {
"Name": service_name, "Name": service_name,
@ -12,7 +12,7 @@ def register_to_consul():
"Address": service_name, # 容器名作为地址 "Address": service_name, # 容器名作为地址
"Port": port, "Port": port,
"Check": { "Check": {
"HTTP": f"http://{service_name}:{port}/health", "TCP": f"{service_name}:{port}",
"Interval": "10s" "Interval": "10s"
} }
} }
@ -22,3 +22,6 @@ def register_to_consul():
print(f"[{service_name}] Registered to Consul") print(f"[{service_name}] Registered to Consul")
except Exception as e: except Exception as e:
print(f"❌ Consul register failed: {e}") print(f"❌ Consul register failed: {e}")
if __name__ == "__main__":
register_to_consul()

View File

@ -1 +1,2 @@
flask flask
aktools

View File

@ -1,6 +1,7 @@
api:
dashboard: true
entryPoints: entryPoints:
web: web:
address: ":80" address: ":80"
http:
middlewares:
compress:
compress: true