963 lines
29 KiB
Python
963 lines
29 KiB
Python
"""服务编排服务,用于管理算法服务的生命周期"""
|
||
|
||
import os
|
||
import json
|
||
import time
|
||
import docker
|
||
import uuid
|
||
from typing import Dict, Any, Optional
|
||
from docker.errors import DockerException, NotFound
|
||
|
||
|
||
class ServiceOrchestrator:
|
||
"""服务编排服务"""
|
||
|
||
def __init__(self):
|
||
"""初始化服务编排器"""
|
||
try:
|
||
# 连接Docker客户端
|
||
self.client = docker.from_env()
|
||
# 测试连接
|
||
self.client.ping()
|
||
print("Docker连接成功")
|
||
except DockerException as e:
|
||
print(f"Docker连接失败: {e}")
|
||
self.client = None
|
||
|
||
def deploy_service(self, service_id: str, service_config: Dict[str, Any], project_info: Dict[str, Any]) -> Dict[str, Any]:
|
||
"""部署服务
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
service_config: 服务配置
|
||
project_info: 项目信息
|
||
|
||
Returns:
|
||
部署结果
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"service_id": service_id,
|
||
"container_id": None,
|
||
"status": "error",
|
||
"api_url": None
|
||
}
|
||
|
||
# 1. 构建Docker镜像
|
||
image_name = self._build_docker_image(service_id, project_info, service_config)
|
||
|
||
# 2. 启动服务容器
|
||
container_id = self._start_service_container(service_id, image_name, service_config)
|
||
|
||
# 3. 验证服务启动
|
||
if not self._verify_service_startup(container_id, service_config):
|
||
return {
|
||
"success": False,
|
||
"error": "服务启动验证失败",
|
||
"service_id": service_id,
|
||
"container_id": container_id,
|
||
"status": "error",
|
||
"api_url": None
|
||
}
|
||
|
||
# 4. 构建API URL
|
||
api_url = f"http://{service_config.get('host', 'localhost')}:{service_config.get('port', 8000)}"
|
||
|
||
return {
|
||
"success": True,
|
||
"service_id": service_id,
|
||
"container_id": container_id,
|
||
"status": "running",
|
||
"api_url": api_url,
|
||
"error": None
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"service_id": service_id,
|
||
"container_id": None,
|
||
"status": "error",
|
||
"api_url": None
|
||
}
|
||
|
||
def start_service(self, service_id: str, container_id: str) -> Dict[str, Any]:
|
||
"""启动服务
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
container_id: 容器ID
|
||
|
||
Returns:
|
||
启动结果
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
# 获取容器
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 启动容器
|
||
container.start()
|
||
|
||
# 验证服务启动
|
||
if not self._verify_service_health(container_id):
|
||
return {
|
||
"success": False,
|
||
"error": "服务健康检查失败",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
return {
|
||
"success": True,
|
||
"service_id": service_id,
|
||
"status": "running",
|
||
"error": None
|
||
}
|
||
except NotFound:
|
||
return {
|
||
"success": False,
|
||
"error": "容器不存在",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
def stop_service(self, service_id: str, container_id: str) -> Dict[str, Any]:
|
||
"""停止服务
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
container_id: 容器ID
|
||
|
||
Returns:
|
||
停止结果
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
# 获取容器
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 停止容器
|
||
container.stop(timeout=30)
|
||
|
||
return {
|
||
"success": True,
|
||
"service_id": service_id,
|
||
"status": "stopped",
|
||
"error": None
|
||
}
|
||
except NotFound:
|
||
return {
|
||
"success": False,
|
||
"error": "容器不存在",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
def restart_service(self, service_id: str, container_id: str) -> Dict[str, Any]:
|
||
"""重启服务
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
container_id: 容器ID
|
||
|
||
Returns:
|
||
重启结果
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
# 获取容器
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 重启容器
|
||
container.restart(timeout=30)
|
||
|
||
# 验证服务启动
|
||
if not self._verify_service_health(container_id):
|
||
return {
|
||
"success": False,
|
||
"error": "服务健康检查失败",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
return {
|
||
"success": True,
|
||
"service_id": service_id,
|
||
"status": "running",
|
||
"error": None
|
||
}
|
||
except NotFound:
|
||
return {
|
||
"success": False,
|
||
"error": "容器不存在",
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"service_id": service_id,
|
||
"status": "error"
|
||
}
|
||
|
||
def delete_service(self, service_id: str, container_id: str, image_name: str) -> Dict[str, Any]:
|
||
"""删除服务
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
container_id: 容器ID
|
||
image_name: 镜像名称
|
||
|
||
Returns:
|
||
删除结果
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"service_id": service_id
|
||
}
|
||
|
||
# 停止并删除容器
|
||
if container_id:
|
||
try:
|
||
container = self.client.containers.get(container_id)
|
||
container.stop(timeout=10)
|
||
container.remove(force=True)
|
||
except NotFound:
|
||
pass
|
||
|
||
# 删除镜像
|
||
if image_name:
|
||
try:
|
||
self.client.images.remove(image_name, force=True)
|
||
except:
|
||
pass
|
||
|
||
return {
|
||
"success": True,
|
||
"service_id": service_id,
|
||
"error": None
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"service_id": service_id
|
||
}
|
||
|
||
def get_service_status(self, container_id: str) -> Dict[str, Any]:
|
||
"""获取服务状态
|
||
|
||
Args:
|
||
container_id: 容器ID
|
||
|
||
Returns:
|
||
服务状态
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"status": "unknown",
|
||
"health": "unknown"
|
||
}
|
||
|
||
# 获取容器
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 获取容器状态
|
||
status = container.status
|
||
|
||
# 检查服务健康状态
|
||
health = "unknown"
|
||
if status == "running":
|
||
if self._verify_service_health(container_id):
|
||
health = "healthy"
|
||
else:
|
||
health = "unhealthy"
|
||
|
||
return {
|
||
"success": True,
|
||
"status": status,
|
||
"health": health,
|
||
"error": None
|
||
}
|
||
except NotFound:
|
||
return {
|
||
"success": False,
|
||
"error": "容器不存在",
|
||
"status": "not_found",
|
||
"health": "unknown"
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"status": "unknown",
|
||
"health": "unknown"
|
||
}
|
||
|
||
def get_service_logs(self, container_id: str, lines: int = 100) -> Dict[str, Any]:
|
||
"""获取服务日志
|
||
|
||
Args:
|
||
container_id: 容器ID
|
||
lines: 日志行数
|
||
|
||
Returns:
|
||
服务日志
|
||
"""
|
||
try:
|
||
if not self.client:
|
||
return {
|
||
"success": False,
|
||
"error": "Docker连接失败",
|
||
"logs": []
|
||
}
|
||
|
||
# 获取容器
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 获取日志
|
||
logs = container.logs(tail=lines).decode('utf-8').split('\n')
|
||
|
||
return {
|
||
"success": True,
|
||
"logs": logs,
|
||
"error": None
|
||
}
|
||
except NotFound:
|
||
return {
|
||
"success": False,
|
||
"error": "容器不存在",
|
||
"logs": []
|
||
}
|
||
except Exception as e:
|
||
return {
|
||
"success": False,
|
||
"error": str(e),
|
||
"logs": []
|
||
}
|
||
|
||
def _build_docker_image(self, service_id: str, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
|
||
"""构建Docker镜像
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
project_info: 项目信息
|
||
service_config: 服务配置
|
||
|
||
Returns:
|
||
镜像名称
|
||
"""
|
||
# 生成镜像名称
|
||
image_name = f"algorithm-service-{service_id}:{service_config.get('version', '1.0.0')}"
|
||
|
||
# 构建上下文目录
|
||
build_context = os.path.join("/tmp", f"service-build-{service_id}")
|
||
os.makedirs(build_context, exist_ok=True)
|
||
|
||
try:
|
||
# 创建Dockerfile
|
||
dockerfile_content = self._generate_dockerfile(project_info, service_config)
|
||
with open(os.path.join(build_context, "Dockerfile"), "w") as f:
|
||
f.write(dockerfile_content)
|
||
|
||
# 复制项目文件(这里简化处理,实际应该复制完整项目)
|
||
# 注意:在实际实现中,应该从算法仓库复制项目文件到构建上下文
|
||
|
||
# 创建服务包装器
|
||
service_wrapper_content = self._generate_service_wrapper(project_info, service_config)
|
||
wrapper_extension = ".py" if project_info["project_type"] == "python" else ".js"
|
||
with open(os.path.join(build_context, f"service_wrapper{wrapper_extension}"), "w") as f:
|
||
f.write(service_wrapper_content)
|
||
|
||
# 创建依赖文件
|
||
self._create_dependency_file(build_context, project_info)
|
||
|
||
# 构建镜像
|
||
print(f"开始构建Docker镜像: {image_name}")
|
||
image, logs = self.client.images.build(
|
||
path=build_context,
|
||
tag=image_name,
|
||
rm=True,
|
||
pull=False
|
||
)
|
||
|
||
# 打印构建日志
|
||
for log in logs:
|
||
if 'stream' in log:
|
||
print(log['stream'], end='')
|
||
|
||
print(f"Docker镜像构建成功: {image_name}")
|
||
return image_name
|
||
finally:
|
||
# 清理构建上下文
|
||
import shutil
|
||
try:
|
||
shutil.rmtree(build_context)
|
||
except:
|
||
pass
|
||
|
||
def _start_service_container(self, service_id: str, image_name: str, service_config: Dict[str, Any]) -> str:
|
||
"""启动服务容器
|
||
|
||
Args:
|
||
service_id: 服务ID
|
||
image_name: 镜像名称
|
||
service_config: 服务配置
|
||
|
||
Returns:
|
||
容器ID
|
||
"""
|
||
# 容器名称
|
||
container_name = f"algorithm-service-{service_id}"
|
||
|
||
# 端口映射
|
||
ports = {
|
||
f"{service_config.get('port', 8000)}/tcp": service_config.get('port', 8000)
|
||
}
|
||
|
||
# 环境变量
|
||
environment = {
|
||
"HOST": service_config.get('host', '0.0.0.0'),
|
||
"PORT": str(service_config.get('port', 8000)),
|
||
"TIMEOUT": str(service_config.get('timeout', 30))
|
||
}
|
||
|
||
# 启动容器
|
||
container = self.client.containers.run(
|
||
image_name,
|
||
name=container_name,
|
||
ports=ports,
|
||
environment=environment,
|
||
detach=True,
|
||
restart_policy={"Name": "unless-stopped"}
|
||
)
|
||
|
||
print(f"容器启动成功: {container.id}")
|
||
return container.id
|
||
|
||
def _verify_service_startup(self, container_id: str, service_config: Dict[str, Any]) -> bool:
|
||
"""验证服务启动
|
||
|
||
Args:
|
||
container_id: 容器ID
|
||
service_config: 服务配置
|
||
|
||
Returns:
|
||
是否启动成功
|
||
"""
|
||
# 等待服务启动
|
||
time.sleep(5)
|
||
|
||
# 验证服务健康状态
|
||
return self._verify_service_health(container_id)
|
||
|
||
def _verify_service_health(self, container_id: str) -> bool:
|
||
"""验证服务健康状态
|
||
|
||
Args:
|
||
container_id: 容器ID
|
||
|
||
Returns:
|
||
是否健康
|
||
"""
|
||
try:
|
||
container = self.client.containers.get(container_id)
|
||
|
||
# 检查容器状态
|
||
if container.status != "running":
|
||
return False
|
||
|
||
# 这里可以添加更详细的健康检查,例如发送HTTP请求到/health端点
|
||
# 简化处理,只检查容器状态
|
||
return True
|
||
except:
|
||
return False
|
||
|
||
def _generate_dockerfile(self, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
|
||
"""生成Dockerfile
|
||
|
||
Args:
|
||
project_info: 项目信息
|
||
service_config: 服务配置
|
||
|
||
Returns:
|
||
Dockerfile内容
|
||
"""
|
||
dockerfile_templates = {
|
||
"python": """
|
||
FROM python:3.9-slim
|
||
|
||
WORKDIR /app
|
||
|
||
# 复制依赖文件
|
||
COPY requirements.txt .
|
||
|
||
# 安装依赖
|
||
RUN pip install --no-cache-dir -r requirements.txt
|
||
|
||
# 复制项目文件
|
||
COPY . .
|
||
|
||
# 复制生成的服务包装器
|
||
COPY service_wrapper.py .
|
||
|
||
# 设置环境变量
|
||
ENV HOST={{host}}
|
||
ENV PORT={{port}}
|
||
ENV TIMEOUT={{timeout}}
|
||
|
||
# 暴露端口
|
||
EXPOSE {{port}}
|
||
|
||
# 启动服务
|
||
CMD ["python", "service_wrapper.py"]
|
||
""",
|
||
"nodejs": """
|
||
FROM node:16-alpine
|
||
|
||
WORKDIR /app
|
||
|
||
# 复制依赖文件
|
||
COPY package.json package-lock.json* .
|
||
|
||
# 安装依赖
|
||
RUN npm install --production
|
||
|
||
# 复制项目文件
|
||
COPY . .
|
||
|
||
# 复制生成的服务包装器
|
||
COPY service_wrapper.js .
|
||
|
||
# 设置环境变量
|
||
ENV HOST={{host}}
|
||
ENV PORT={{port}}
|
||
ENV TIMEOUT={{timeout}}
|
||
|
||
# 暴露端口
|
||
EXPOSE {{port}}
|
||
|
||
# 启动服务
|
||
CMD ["node", "service_wrapper.js"]
|
||
"""
|
||
}
|
||
|
||
template = dockerfile_templates.get(project_info["project_type"], dockerfile_templates["python"])
|
||
|
||
# 替换模板变量
|
||
template = template.replace("{{host}}", service_config.get("host", "0.0.0.0"))
|
||
template = template.replace("{{port}}", str(service_config.get("port", 8000)))
|
||
template = template.replace("{{timeout}}", str(service_config.get("timeout", 30)))
|
||
|
||
return template
|
||
|
||
def _generate_service_wrapper(self, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
|
||
"""生成服务包装器
|
||
|
||
Args:
|
||
project_info: 项目信息
|
||
service_config: 服务配置
|
||
|
||
Returns:
|
||
服务包装器代码
|
||
"""
|
||
if project_info["project_type"] == "python":
|
||
return '''
|
||
# Python HTTP服务包装器
|
||
|
||
import os
|
||
import sys
|
||
import json
|
||
import time
|
||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||
|
||
# 添加项目路径到Python路径
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
|
||
# 尝试导入算法模块
|
||
try:
|
||
# 尝试导入主要模块
|
||
import algorithm
|
||
algorithm_module = algorithm
|
||
print("算法模块导入成功")
|
||
except Exception as e:
|
||
print(f"算法模块导入失败: {e}")
|
||
algorithm_module = None
|
||
|
||
# 服务配置
|
||
HOST = os.environ.get("HOST", "0.0.0.0")
|
||
PORT = int(os.environ.get("PORT", "8000"))
|
||
TIMEOUT = int(os.environ.get("TIMEOUT", "30"))
|
||
|
||
class AlgorithmRequestHandler(BaseHTTPRequestHandler):
|
||
"""算法请求处理器"""
|
||
|
||
def do_POST(self):
|
||
"""处理POST请求"""
|
||
try:
|
||
# 读取请求体
|
||
content_length = int(self.headers['Content-Length'])
|
||
post_data = self.rfile.read(content_length)
|
||
|
||
# 解析请求数据
|
||
request_data = json.loads(post_data.decode('utf-8'))
|
||
|
||
# 记录请求开始时间
|
||
start_time = time.time()
|
||
|
||
# 调用算法
|
||
result = self._call_algorithm(request_data)
|
||
|
||
# 计算响应时间
|
||
response_time = time.time() - start_time
|
||
|
||
# 构建响应
|
||
response = {
|
||
"success": True,
|
||
"result": result,
|
||
"response_time": round(response_time, 4),
|
||
"message": "算法执行成功"
|
||
}
|
||
|
||
# 发送响应
|
||
self.send_response(200)
|
||
self.send_header('Content-type', 'application/json')
|
||
self.end_headers()
|
||
self.wfile.write(json.dumps(response).encode('utf-8'))
|
||
|
||
except Exception as e:
|
||
# 构建错误响应
|
||
error_response = {
|
||
"success": False,
|
||
"error": str(e),
|
||
"message": "算法执行失败"
|
||
}
|
||
|
||
# 发送错误响应
|
||
self.send_response(400)
|
||
self.send_header('Content-type', 'application/json')
|
||
self.end_headers()
|
||
self.wfile.write(json.dumps(error_response).encode('utf-8'))
|
||
|
||
def do_GET(self):
|
||
"""处理GET请求"""
|
||
if self.path == "/health":
|
||
# 健康检查
|
||
self._handle_health_check()
|
||
elif self.path == "/info":
|
||
# 服务信息
|
||
self._handle_info()
|
||
else:
|
||
# 404响应
|
||
self.send_response(404)
|
||
self.send_header('Content-type', 'application/json')
|
||
self.end_headers()
|
||
self.wfile.write(json.dumps({"error": "Not Found"}).encode('utf-8'))
|
||
|
||
def _call_algorithm(self, request_data):
|
||
"""调用算法
|
||
|
||
Args:
|
||
request_data: 请求数据
|
||
|
||
Returns:
|
||
算法执行结果
|
||
"""
|
||
if algorithm_module is None:
|
||
raise Exception("算法模块未加载")
|
||
|
||
# 尝试调用算法的主要函数
|
||
try:
|
||
# 检查是否有predict函数
|
||
if hasattr(algorithm_module, 'predict'):
|
||
return algorithm_module.predict(request_data)
|
||
# 检查是否有run函数
|
||
elif hasattr(algorithm_module, 'run'):
|
||
return algorithm_module.run(request_data)
|
||
# 检查是否有main函数
|
||
elif hasattr(algorithm_module, 'main'):
|
||
return algorithm_module.main(request_data)
|
||
else:
|
||
raise Exception("未找到算法执行函数")
|
||
except Exception as e:
|
||
raise Exception(f"算法执行失败: {e}")
|
||
|
||
def _handle_health_check(self):
|
||
"""处理健康检查"""
|
||
self.send_response(200)
|
||
self.send_header('Content-type', 'application/json')
|
||
self.end_headers()
|
||
self.wfile.write(json.dumps({"status": "healthy", "service": "{{service_name}}"}).encode('utf-8'))
|
||
|
||
def _handle_info(self):
|
||
"""处理服务信息请求"""
|
||
info = {
|
||
"service": "{{service_name}}",
|
||
"version": "{{service_version}}",
|
||
"host": HOST,
|
||
"port": PORT,
|
||
"timeout": TIMEOUT,
|
||
"algorithm_loaded": algorithm_module is not None
|
||
}
|
||
|
||
self.send_response(200)
|
||
self.send_header('Content-type', 'application/json')
|
||
self.end_headers()
|
||
self.wfile.write(json.dumps(info).encode('utf-8'))
|
||
|
||
def run_server():
|
||
"""启动服务"""
|
||
server = HTTPServer((HOST, PORT), AlgorithmRequestHandler)
|
||
print(f"服务启动成功,监听地址: {HOST}:{PORT}")
|
||
print(f"健康检查地址: http://{HOST}:{PORT}/health")
|
||
print(f"服务信息地址: http://{HOST}:{PORT}/info")
|
||
|
||
try:
|
||
server.serve_forever()
|
||
except KeyboardInterrupt:
|
||
print("服务停止")
|
||
server.shutdown()
|
||
|
||
if __name__ == "__main__":
|
||
run_server()
|
||
'''.replace("{{service_name}}", service_config.get("name", "algorithm-service")).replace("{{service_version}}", service_config.get("version", "1.0.0"))
|
||
else:
|
||
return '''
|
||
// Node.js HTTP服务包装器
|
||
|
||
const http = require('http');
|
||
const url = require('url');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
// 服务配置
|
||
const HOST = process.env.HOST || '0.0.0.0';
|
||
const PORT = process.env.PORT || 8000;
|
||
const TIMEOUT = process.env.TIMEOUT || 30;
|
||
|
||
// 尝试导入算法模块
|
||
let algorithmModule = null;
|
||
try {
|
||
// 尝试导入主要模块
|
||
algorithmModule = require('./algorithm');
|
||
console.log('算法模块导入成功');
|
||
} catch (e) {
|
||
console.error('算法模块导入失败:', e);
|
||
algorithmModule = null;
|
||
}
|
||
|
||
/**
|
||
* 调用算法
|
||
* @param {Object} requestData 请求数据
|
||
* @returns {Object} 算法执行结果
|
||
*/
|
||
function callAlgorithm(requestData) {
|
||
if (!algorithmModule) {
|
||
throw new Error('算法模块未加载');
|
||
}
|
||
|
||
// 尝试调用算法的主要函数
|
||
try {
|
||
if (algorithmModule.predict) {
|
||
return algorithmModule.predict(requestData);
|
||
} else if (algorithmModule.run) {
|
||
return algorithmModule.run(requestData);
|
||
} else if (algorithmModule.main) {
|
||
return algorithmModule.main(requestData);
|
||
} else {
|
||
throw new Error('未找到算法执行函数');
|
||
}
|
||
} catch (e) {
|
||
throw new Error(`算法执行失败: ${e.message}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理请求
|
||
* @param {http.IncomingMessage} req 请求对象
|
||
* @param {http.ServerResponse} res 响应对象
|
||
*/
|
||
function handleRequest(req, res) {
|
||
const parsedUrl = url.parse(req.url, true);
|
||
const pathname = parsedUrl.pathname;
|
||
|
||
// 设置响应头
|
||
res.setHeader('Content-Type', 'application/json');
|
||
|
||
if (req.method === 'GET') {
|
||
if (pathname === '/health') {
|
||
// 健康检查
|
||
res.writeHead(200);
|
||
res.end(JSON.stringify({ status: 'healthy', service: '{{service_name}}' }));
|
||
} else if (pathname === '/info') {
|
||
// 服务信息
|
||
const info = {
|
||
service: '{{service_name}}',
|
||
version: '{{service_version}}',
|
||
host: HOST,
|
||
port: PORT,
|
||
timeout: TIMEOUT,
|
||
algorithm_loaded: algorithmModule !== null
|
||
};
|
||
res.writeHead(200);
|
||
res.end(JSON.stringify(info));
|
||
} else {
|
||
// 404响应
|
||
res.writeHead(404);
|
||
res.end(JSON.stringify({ error: 'Not Found' }));
|
||
}
|
||
} else if (req.method === 'POST') {
|
||
let body = '';
|
||
|
||
// 读取请求体
|
||
req.on('data', chunk => {
|
||
body += chunk.toString();
|
||
});
|
||
|
||
req.on('end', () => {
|
||
try {
|
||
// 解析请求数据
|
||
const requestData = JSON.parse(body);
|
||
|
||
// 记录请求开始时间
|
||
const startTime = Date.now();
|
||
|
||
// 调用算法
|
||
const result = callAlgorithm(requestData);
|
||
|
||
// 计算响应时间
|
||
const responseTime = (Date.now() - startTime) / 1000;
|
||
|
||
// 构建响应
|
||
const response = {
|
||
success: true,
|
||
result: result,
|
||
response_time: responseTime.toFixed(4),
|
||
message: '算法执行成功'
|
||
};
|
||
|
||
// 发送响应
|
||
res.writeHead(200);
|
||
res.end(JSON.stringify(response));
|
||
} catch (e) {
|
||
// 构建错误响应
|
||
const errorResponse = {
|
||
success: false,
|
||
error: e.message,
|
||
message: '算法执行失败'
|
||
};
|
||
|
||
// 发送错误响应
|
||
res.writeHead(400);
|
||
res.end(JSON.stringify(errorResponse));
|
||
}
|
||
});
|
||
} else {
|
||
// 不支持的方法
|
||
res.writeHead(405);
|
||
res.end(JSON.stringify({ error: 'Method Not Allowed' }));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 启动服务
|
||
*/
|
||
function startServer() {
|
||
const server = http.createServer(handleRequest);
|
||
|
||
server.listen(PORT, HOST, () => {
|
||
console.log(`服务启动成功,监听地址: ${HOST}:${PORT}`);
|
||
console.log(`健康检查地址: http://${HOST}:${PORT}/health`);
|
||
console.log(`服务信息地址: http://${HOST}:${PORT}/info`);
|
||
});
|
||
|
||
server.on('error', (error) => {
|
||
console.error('服务启动失败:', error);
|
||
});
|
||
}
|
||
|
||
// 启动服务
|
||
startServer();
|
||
'''.replace("{{service_name}}", service_config.get("name", "algorithm-service")).replace("{{service_version}}", service_config.get("version", "1.0.0"))
|
||
|
||
def _create_dependency_file(self, build_context: str, project_info: Dict[str, Any]):
|
||
"""创建依赖文件
|
||
|
||
Args:
|
||
build_context: 构建上下文目录
|
||
project_info: 项目信息
|
||
"""
|
||
if project_info["project_type"] == "python":
|
||
# 创建requirements.txt
|
||
with open(os.path.join(build_context, "requirements.txt"), "w") as f:
|
||
f.write("""
|
||
# 基础依赖
|
||
http.server
|
||
json
|
||
|
||
# 算法依赖
|
||
# 注意:在实际实现中,应该从项目的requirements.txt复制依赖
|
||
""")
|
||
elif project_info["project_type"] == "nodejs":
|
||
# 创建package.json
|
||
package_data = {
|
||
"name": "algorithm-service",
|
||
"version": "1.0.0",
|
||
"description": "Algorithm service wrapper",
|
||
"main": "service_wrapper.js",
|
||
"scripts": {
|
||
"start": "node service_wrapper.js"
|
||
},
|
||
"dependencies": {
|
||
# 基础依赖
|
||
}
|
||
}
|
||
with open(os.path.join(build_context, "package.json"), "w") as f:
|
||
json.dump(package_data, f, indent=2)
|