添加MySQL数据库配置,更新后端API以支持新的实例搜索功能,并修改前端调用接口以适应新API。

This commit is contained in:
wangqifan 2025-04-03 12:52:37 +08:00
parent 0c9cab7901
commit d0b3ed2427
7 changed files with 180 additions and 5 deletions

View File

@ -1,3 +1,9 @@
AWS_ACCESS_KEY_ID=AKIAVIOZF67K6HNCUJ5Y
AWS_SECRET_ACCESS_KEY=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
AWS_DEFAULT_REGION=us-east-1
AWS_DEFAULT_REGION=us-east-1
# MySQL数据库配置
MYSQL_HOST=47.76.209.7
MYSQL_USER=aws_price
MYSQL_PASSWORD=123456
MYSQL_DATABASE=aws_price

View File

@ -5,6 +5,9 @@ WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
curl \
default-libmysqlclient-dev \
gcc \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件

View File

@ -1,8 +1,9 @@
from fastapi import APIRouter, HTTPException
from ..models.schemas import PriceRequest, PriceComparison, InstanceSearchRequest
from ..models.schemas import PriceRequest, PriceComparison, InstanceSearchRequest, InstanceSearchRequestV2
from ..core.config import AWS_REGION_NAMES, AZURE_REGION_NAMES, ALIYUN_REGION_NAMES
from ..core.instance_data import get_instance_info
from ..services import calculate_price
from ..services.aws.pricing_v2 import search_instances_v2
from typing import Dict, List, Any
router = APIRouter(prefix="/api")
@ -100,6 +101,26 @@ async def search_instances(request: InstanceSearchRequest):
print(f"搜索实例时出错: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/search-instances-v2")
async def search_instances_v2_api(request: InstanceSearchRequestV2):
"""
第二套搜索API - 通过MySQL数据库搜索符合条件的AWS实例
"""
try:
# 调用服务层函数
instances = await search_instances_v2(
region=request.region,
cpu_cores=request.cpu_cores,
memory_gb=request.memory_gb,
disk_gb=request.disk_gb,
operating_system=request.operating_system
)
return instances
except Exception as e:
print(f"搜索实例时出错: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/compare-prices")
async def compare_prices(comparison: PriceComparison):
"""比较不同配置的价格"""

View File

@ -19,4 +19,12 @@ class InstanceSearchRequest(BaseModel):
disk_gb: Optional[int] = None
region: Optional[str] = None
operating_system: Optional[str] = "Linux"
platform: Optional[str] = "aws" # 新增平台字段默认为AWS
platform: Optional[str] = "aws" # 新增平台字段默认为AWS
# 第二套价格计算API的数据模型
class InstanceSearchRequestV2(BaseModel):
cpu_cores: Optional[int] = None
memory_gb: Optional[float] = None
disk_gb: Optional[int] = None
region: Optional[str] = None
operating_system: Optional[str] = "Linux"

View File

@ -0,0 +1,136 @@
import mysql.connector
from mysql.connector import Error
import os
from dotenv import load_dotenv
from typing import List, Dict, Any, Optional
from ...core.config import AWS_REGION_NAMES_EN, AWS_PRICING_EBS
# 加载环境变量
load_dotenv()
# 数据库连接配置
DB_CONFIG = {
"host": os.getenv("MYSQL_HOST", "localhost"),
"user": os.getenv("MYSQL_USER", "root"),
"password": os.getenv("MYSQL_PASSWORD", ""),
"database": os.getenv("MYSQL_DATABASE", "aws_pricing")
}
async def calculate_ebs_price(region: str, disk_gb: int) -> float:
"""计算EBS存储价格"""
# 从配置中获取价格,如果没有则使用默认价格
if region in AWS_PRICING_EBS:
price_dimensions = AWS_PRICING_EBS[region]
else:
price_dimensions = 0.1
return price_dimensions * disk_gb
async def search_instances_v2(
region: Optional[str] = None,
cpu_cores: Optional[int] = None,
memory_gb: Optional[float] = None,
disk_gb: Optional[int] = None,
operating_system: str = "Linux"
) -> List[Dict[str, Any]]:
"""
从MySQL数据库搜索符合条件的AWS实例
"""
try:
# 获取区域的英文名称
region_name = None
if region:
region_name = AWS_REGION_NAMES_EN.get(region)
# 连接到MySQL数据库
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor(dictionary=True)
# 构建SQL查询
query = """
SELECT
id,
locations,
area_en,
area_cn,
instance_type,
price,
operating_system,
vcpu,
memory,
updatetime
FROM aws_price
WHERE 1=1
"""
params = []
# 添加过滤条件
if region_name:
query += " AND area_en = %s"
params.append(region_name)
if cpu_cores:
query += " AND vcpu = %s"
params.append(cpu_cores)
if memory_gb:
query += " AND memory = %s"
params.append(memory_gb)
if operating_system:
query += " AND operating_system = %s"
params.append(operating_system)
# 执行查询
cursor.execute(query, params)
results = cursor.fetchall()
# 处理结果
instances = []
for row in results:
hourly_price = float(row['price'])
monthly_price = hourly_price * 730 # 730小时/月
# 计算存储价格
disk_monthly_price = 0
if disk_gb and disk_gb > 0:
# 从区域代码获取区域英文名称,反向查找
region_code = None
for code, name in AWS_REGION_NAMES_EN.items():
if name == row['area_en']:
region_code = code
break
disk_monthly_price = await calculate_ebs_price(region_code, disk_gb) if region_code else 0
# 计算总价格
total_monthly_price = monthly_price + disk_monthly_price
instances.append({
"instance_type": row['instance_type'],
"description": f"{row['vcpu']}{row['memory']}GB {row['instance_type']}",
"cpu": row['vcpu'],
"memory": row['memory'],
"disk_gb": disk_gb if disk_gb else 0,
"hourly_price": hourly_price,
"monthly_price": monthly_price,
"disk_monthly_price": disk_monthly_price,
"total_monthly_price": total_monthly_price,
"region": row['area_en'],
"operating_system": row['operating_system']
})
# 按总价格排序
instances.sort(key=lambda x: x['total_monthly_price'])
# 关闭连接
cursor.close()
conn.close()
return instances
except Error as e:
print(f"MySQL数据库错误: {e}")
raise Exception(f"数据库查询错误: {e}")
except Exception as e:
print(f"搜索实例时出错: {e}")
raise Exception(f"搜索实例时出错: {e}")

View File

@ -6,4 +6,5 @@ pydantic==2.4.2
pandas==2.1.3
python-multipart==0.0.6
requests==2.31.0
httpx==0.25.2
httpx==0.25.2
mysql-connector-python==8.2.0

View File

@ -63,7 +63,7 @@ const apiService = {
// 搜索实例
searchInstances: async (params) => {
try {
const response = await apiClient.post('/api/search-instances', params)
const response = await apiClient.post('/api/search-instances-v2', params)
return response.data
} catch (error) {
console.error('搜索实例失败:', error)