Files
algorithm/backend/app/services/service_generator.py
2026-02-08 14:42:58 +08:00

978 lines
40 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""服务生成器,用于生成算法服务包装器"""
import os
import jinja2
from typing import Dict, Any, Optional
class ServiceGenerator:
"""服务生成器"""
def __init__(self):
"""初始化服务生成器"""
# 初始化Jinja2模板引擎
self.template_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), "templates")),
autoescape=False
)
# 确保模板目录存在
template_dir = os.path.join(os.path.dirname(__file__), "templates")
if not os.path.exists(template_dir):
os.makedirs(template_dir)
# 创建默认模板
self._create_default_templates(template_dir)
def generate_service(self, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> Dict[str, Any]:
"""生成服务包装器
Args:
project_info: 项目分析信息
service_config: 服务配置
Returns:
包含生成结果的字典
"""
try:
# 1. 根据项目类型选择模板
template_name = self._select_template(project_info["project_type"], service_config["service_type"])
# 2. 生成服务代码
service_code = self._generate_service_code(template_name, project_info, service_config)
# 3. 生成Dockerfile
dockerfile = self._generate_dockerfile(project_info, service_config)
# 4. 生成配置文件
config_files = self._generate_config_files(service_config)
return {
"success": True,
"service_code": service_code,
"dockerfile": dockerfile,
"config_files": config_files,
"error": None
}
except Exception as e:
return {
"success": False,
"error": str(e),
"service_code": None,
"dockerfile": None,
"config_files": None
}
def _select_template(self, project_type: str, service_type: str) -> str:
"""选择服务模板
Args:
project_type: 项目类型
service_type: 服务类型
Returns:
模板名称
"""
# 根据项目类型和服务类型选择模板
template_map = {
"python": {
"http": "python_http_service.py.j2",
"grpc": "python_grpc_service.py.j2",
"mq": "python_mq_service.py.j2"
},
"nodejs": {
"http": "nodejs_http_service.js.j2",
"grpc": "nodejs_grpc_service.js.j2",
"mq": "nodejs_mq_service.js.j2"
}
}
return template_map.get(project_type, {}).get(service_type, "python_http_service.py.j2")
def _generate_service_code(self, template_name: str, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
"""生成服务代码
Args:
template_name: 模板名称
project_info: 项目信息
service_config: 服务配置
Returns:
生成的服务代码
"""
try:
# 加载模板
template = self.template_env.get_template(template_name)
# 准备模板数据
template_data = {
"project_name": service_config.get("name", "algorithm-service"),
"project_type": project_info["project_type"],
"entry_point": project_info["entry_point"],
"api_pattern": project_info["api_pattern"],
"dependencies": project_info["dependencies"],
"service_config": service_config,
"host": service_config.get("host", "0.0.0.0"),
"port": service_config.get("port", 8000),
"timeout": service_config.get("timeout", 30),
"health_check_path": service_config.get("health_check_path", "/health")
}
# 渲染模板
return template.render(**template_data)
except Exception as e:
# 如果模板不存在生成默认的Python HTTP服务
if project_info["project_type"] == "python":
return self._generate_default_python_http_service(project_info, service_config)
elif project_info["project_type"] == "nodejs":
return self._generate_default_nodejs_http_service(project_info, service_config)
else:
raise e
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_config_files(self, service_config: Dict[str, Any]) -> Dict[str, str]:
"""生成配置文件
Args:
service_config: 服务配置
Returns:
配置文件字典
"""
config_files = {}
# 生成环境变量文件
env_content = """
# Service Configuration
HOST={{host}}
PORT={{port}}
TIMEOUT={{timeout}}
# Service Metadata
SERVICE_NAME={{name}}
SERVICE_VERSION={{version}}
"""
env_content = env_content.replace("{{host}}", service_config.get("host", "0.0.0.0"))
env_content = env_content.replace("{{port}}", str(service_config.get("port", 8000)))
env_content = env_content.replace("{{timeout}}", str(service_config.get("timeout", 30)))
env_content = env_content.replace("{{name}}", service_config.get("name", "algorithm-service"))
env_content = env_content.replace("{{version}}", service_config.get("version", "1.0.0"))
config_files[".env"] = env_content
# 生成docker-compose.yml
docker_compose_content = """
version: '3.8'
services:
{{name}}:
build: .
ports:
- "{{port}}:{{port}}"
environment:
- HOST={{host}}
- PORT={{port}}
- TIMEOUT={{timeout}}
restart: unless-stopped
"""
docker_compose_content = docker_compose_content.replace("{{name}}", service_config.get("name", "algorithm-service"))
docker_compose_content = docker_compose_content.replace("{{port}}", str(service_config.get("port", 8000)))
docker_compose_content = docker_compose_content.replace("{{host}}", service_config.get("host", "0.0.0.0"))
docker_compose_content = docker_compose_content.replace("{{timeout}}", str(service_config.get("timeout", 30)))
config_files["docker-compose.yml"] = docker_compose_content
return config_files
def _generate_default_python_http_service(self, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
"""生成默认的Python HTTP服务
Args:
project_info: 项目信息
service_config: 服务配置
Returns:
生成的服务代码
"""
# 使用简单的字符串拼接
service_code = "# Python HTTP服务包装器\n"
service_code += "\n"
service_code += "import os\n"
service_code += "import sys\n"
service_code += "import json\n"
service_code += "import time\n"
service_code += "from http.server import HTTPServer, BaseHTTPRequestHandler\n"
service_code += "\n"
service_code += "# 添加项目路径到Python路径\n"
service_code += "sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))\n"
service_code += "\n"
service_code += "# 尝试导入算法模块\n"
service_code += "try:\n"
service_code += " # 根据入口点导入算法\n"
service_code += " if '{{entry_point}}' == '':\n"
service_code += " # 尝试导入主要模块\n"
service_code += " import algorithm\n"
service_code += " algorithm_module = algorithm\n"
service_code += " else:\n"
service_code += " # 动态导入入口点\n"
service_code += " import importlib.util\n"
service_code += " spec = importlib.util.spec_from_file_location('algorithm_module', '{{entry_point}}')\n"
service_code += " algorithm_module = importlib.util.module_from_spec(spec)\n"
service_code += " spec.loader.exec_module(algorithm_module)\n"
service_code += " print('算法模块导入成功')\n"
service_code += "except Exception as e:\n"
service_code += " print(f'算法模块导入失败: {e}')\n"
service_code += " algorithm_module = None\n"
service_code += "\n"
service_code += "# 服务配置\n"
service_code += "HOST = os.environ.get('HOST', '0.0.0.0')\n"
service_code += "PORT = int(os.environ.get('PORT', '{{port}}'))\n"
service_code += "TIMEOUT = int(os.environ.get('TIMEOUT', '{{timeout}}'))\n"
service_code += "\n"
service_code += "class AlgorithmRequestHandler(BaseHTTPRequestHandler):\n"
service_code += " '''算法请求处理器'''\n"
service_code += " \n"
service_code += " def do_POST(self):\n"
service_code += " '''处理POST请求'''\n"
service_code += " try:\n"
service_code += " # 读取请求体\n"
service_code += " content_length = int(self.headers['Content-Length'])\n"
service_code += " post_data = self.rfile.read(content_length)\n"
service_code += " \n"
service_code += " # 解析请求数据\n"
service_code += " request_data = json.loads(post_data.decode('utf-8'))\n"
service_code += " \n"
service_code += " # 记录请求开始时间\n"
service_code += " start_time = time.time()\n"
service_code += " \n"
service_code += " # 调用算法\n"
service_code += " result = self._call_algorithm(request_data)\n"
service_code += " \n"
service_code += " # 计算响应时间\n"
service_code += " response_time = time.time() - start_time\n"
service_code += " \n"
service_code += " # 构建响应\n"
service_code += " response = {\n"
service_code += " 'success': True,\n"
service_code += " 'result': result,\n"
service_code += " 'response_time': round(response_time, 4),\n"
service_code += " 'message': '算法执行成功'\n"
service_code += " }\n"
service_code += " \n"
service_code += " # 发送响应\n"
service_code += " self.send_response(200)\n"
service_code += " self.send_header('Content-type', 'application/json')\n"
service_code += " self.end_headers()\n"
service_code += " self.wfile.write(json.dumps(response).encode('utf-8'))\n"
service_code += " \n"
service_code += " except Exception as e:\n"
service_code += " # 构建错误响应\n"
service_code += " error_response = {\n"
service_code += " 'success': False,\n"
service_code += " 'error': str(e),\n"
service_code += " 'message': '算法执行失败'\n"
service_code += " }\n"
service_code += " \n"
service_code += " # 发送错误响应\n"
service_code += " self.send_response(400)\n"
service_code += " self.send_header('Content-type', 'application/json')\n"
service_code += " self.end_headers()\n"
service_code += " self.wfile.write(json.dumps(error_response).encode('utf-8'))\n"
service_code += " \n"
service_code += " def do_GET(self):\n"
service_code += " '''处理GET请求'''\n"
service_code += " if self.path == '/health':\n"
service_code += " # 健康检查\n"
service_code += " self._handle_health_check()\n"
service_code += " elif self.path == '/info':\n"
service_code += " # 服务信息\n"
service_code += " self._handle_info()\n"
service_code += " else:\n"
service_code += " # 404响应\n"
service_code += " self.send_response(404)\n"
service_code += " self.send_header('Content-type', 'application/json')\n"
service_code += " self.end_headers()\n"
service_code += " self.wfile.write(json.dumps({'error': 'Not Found'}).encode('utf-8'))\n"
service_code += " \n"
service_code += " def _call_algorithm(self, request_data):\n"
service_code += " '''调用算法\n"
service_code += " \n"
service_code += " Args:\n"
service_code += " request_data: 请求数据\n"
service_code += " \n"
service_code += " Returns:\n"
service_code += " 算法执行结果\n"
service_code += " '''\n"
service_code += " if algorithm_module is None:\n"
service_code += " raise Exception('算法模块未加载')\n"
service_code += " \n"
service_code += " # 尝试调用算法的主要函数\n"
service_code += " try:\n"
service_code += " # 检查是否有predict函数\n"
service_code += " if hasattr(algorithm_module, 'predict'):\n"
service_code += " return algorithm_module.predict(request_data)\n"
service_code += " # 检查是否有run函数\n"
service_code += " elif hasattr(algorithm_module, 'run'):\n"
service_code += " return algorithm_module.run(request_data)\n"
service_code += " # 检查是否有main函数\n"
service_code += " elif hasattr(algorithm_module, 'main'):\n"
service_code += " return algorithm_module.main(request_data)\n"
service_code += " else:\n"
service_code += " raise Exception('未找到算法执行函数')\n"
service_code += " except Exception as e:\n"
service_code += " raise Exception(f'算法执行失败: {e}')\n"
service_code += " \n"
service_code += " def _handle_health_check(self):\n"
service_code += " '''处理健康检查'''\n"
service_code += " self.send_response(200)\n"
service_code += " self.send_header('Content-type', 'application/json')\n"
service_code += " self.end_headers()\n"
service_code += " self.wfile.write(json.dumps({'status': 'healthy', 'service': '{{name}}'}).encode('utf-8'))\n"
service_code += " \n"
service_code += " def _handle_info(self):\n"
service_code += " '''处理服务信息请求'''\n"
service_code += " info = {\n"
service_code += " 'service': '{{name}}',\n"
service_code += " 'version': '{{version}}',\n"
service_code += " 'host': HOST,\n"
service_code += " 'port': PORT,\n"
service_code += " 'timeout': TIMEOUT,\n"
service_code += " 'algorithm_loaded': algorithm_module is not None\n"
service_code += " }\n"
service_code += " \n"
service_code += " self.send_response(200)\n"
service_code += " self.send_header('Content-type', 'application/json')\n"
service_code += " self.end_headers()\n"
service_code += " self.wfile.write(json.dumps(info).encode('utf-8'))\n"
service_code += "\n"
service_code += "def run_server():\n"
service_code += " '''启动服务'''\n"
service_code += " server = HTTPServer((HOST, PORT), AlgorithmRequestHandler)\n"
service_code += " print(f'服务启动成功,监听地址: {HOST}:{PORT}')\n"
service_code += " print(f'健康检查地址: http://{HOST}:{PORT}/health')\n"
service_code += " print(f'服务信息地址: http://{HOST}:{PORT}/info')\n"
service_code += " \n"
service_code += " try:\n"
service_code += " server.serve_forever()\n"
service_code += " except KeyboardInterrupt:\n"
service_code += " print('服务停止')\n"
service_code += " server.shutdown()\n"
service_code += "\n"
service_code += "if __name__ == '__main__':\n"
service_code += " run_server()\n"
# 替换模板变量
service_code = service_code.replace("{{entry_point}}", project_info.get("entry_point", ""))
service_code = service_code.replace("{{port}}", str(service_config.get("port", 8000)))
service_code = service_code.replace("{{timeout}}", str(service_config.get("timeout", 30)))
service_code = service_code.replace("{{name}}", service_config.get("name", "algorithm-service"))
service_code = service_code.replace("{{version}}", service_config.get("version", "1.0.0"))
return service_code
def _generate_default_nodejs_http_service(self, project_info: Dict[str, Any], service_config: Dict[str, Any]) -> str:
"""生成默认的Node.js HTTP服务
Args:
project_info: 项目信息
service_config: 服务配置
Returns:
生成的服务代码
"""
# 使用简单的字符串拼接
service_code = "// Node.js HTTP服务包装器\n"
service_code += "\n"
service_code += "const http = require('http');\n"
service_code += "const url = require('url');\n"
service_code += "const fs = require('fs');\n"
service_code += "const path = require('path');\n"
service_code += "\n"
service_code += "// 服务配置\n"
service_code += "const HOST = process.env.HOST || '0.0.0.0';\n"
service_code += "const PORT = process.env.PORT || {{port}};\n"
service_code += "const TIMEOUT = process.env.TIMEOUT || {{timeout}};\n"
service_code += "\n"
service_code += "// 尝试导入算法模块\n"
service_code += "let algorithmModule = null;\n"
service_code += "try {\n"
service_code += " // 根据入口点导入算法\n"
service_code += " if ('{{entry_point}}' === '') {\n"
service_code += " // 尝试导入主要模块\n"
service_code += " algorithmModule = require('./algorithm');\n"
service_code += " } else {\n"
service_code += " // 导入入口点\n"
service_code += " algorithmModule = require('./{{entry_point}}');\n"
service_code += " }\n"
service_code += " console.log('算法模块导入成功');\n"
service_code += "} catch (e) {\n"
service_code += " console.error('算法模块导入失败:', e);\n"
service_code += " algorithmModule = null;\n"
service_code += "}\n"
service_code += "\n"
service_code += "/**\n"
service_code += " * 调用算法\n"
service_code += " * @param {Object} requestData 请求数据\n"
service_code += " * @returns {Object} 算法执行结果\n"
service_code += " */\n"
service_code += "function callAlgorithm(requestData) {\n"
service_code += " if (!algorithmModule) {\n"
service_code += " throw new Error('算法模块未加载');\n"
service_code += " }\n"
service_code += " \n"
service_code += " // 尝试调用算法的主要函数\n"
service_code += " try {\n"
service_code += " if (algorithmModule.predict) {\n"
service_code += " return algorithmModule.predict(requestData);\n"
service_code += " } else if (algorithmModule.run) {\n"
service_code += " return algorithmModule.run(requestData);\n"
service_code += " } else if (algorithmModule.main) {\n"
service_code += " return algorithmModule.main(requestData);\n"
service_code += " } else {\n"
service_code += " throw new Error('未找到算法执行函数');\n"
service_code += " }\n"
service_code += " } catch (e) {\n"
service_code += " throw new Error(`算法执行失败: ${e.message}`);\n"
service_code += " }\n"
service_code += "}\n"
service_code += "\n"
service_code += "/**\n"
service_code += " * 处理请求\n"
service_code += " * @param {http.IncomingMessage} req 请求对象\n"
service_code += " * @param {http.ServerResponse} res 响应对象\n"
service_code += " */\n"
service_code += "function handleRequest(req, res) {\n"
service_code += " const parsedUrl = url.parse(req.url, true);\n"
service_code += " const pathname = parsedUrl.pathname;\n"
service_code += " \n"
service_code += " // 设置响应头\n"
service_code += " res.setHeader('Content-Type', 'application/json');\n"
service_code += " \n"
service_code += " if (req.method === 'GET') {\n"
service_code += " if (pathname === '/health') {\n"
service_code += " // 健康检查\n"
service_code += " res.writeHead(200);\n"
service_code += " res.end(JSON.stringify({ status: 'healthy', service: '{{name}}' }));\n"
service_code += " } else if (pathname === '/info') {\n"
service_code += " // 服务信息\n"
service_code += " const info = {\n"
service_code += " service: '{{name}}',\n"
service_code += " version: '{{version}}',\n"
service_code += " host: HOST,\n"
service_code += " port: PORT,\n"
service_code += " timeout: TIMEOUT,\n"
service_code += " algorithm_loaded: algorithmModule !== null\n"
service_code += " };\n"
service_code += " res.writeHead(200);\n"
service_code += " res.end(JSON.stringify(info));\n"
service_code += " } else {\n"
service_code += " // 404响应\n"
service_code += " res.writeHead(404);\n"
service_code += " res.end(JSON.stringify({ error: 'Not Found' }));\n"
service_code += " }\n"
service_code += " } else if (req.method === 'POST') {\n"
service_code += " let body = '';\n"
service_code += " \n"
service_code += " // 读取请求体\n"
service_code += " req.on('data', chunk => {\n"
service_code += " body += chunk.toString();\n"
service_code += " });\n"
service_code += " \n"
service_code += " req.on('end', () => {\n"
service_code += " try {\n"
service_code += " // 解析请求数据\n"
service_code += " const requestData = JSON.parse(body);\n"
service_code += " \n"
service_code += " // 记录请求开始时间\n"
service_code += " const startTime = Date.now();\n"
service_code += " \n"
service_code += " // 调用算法\n"
service_code += " const result = callAlgorithm(requestData);\n"
service_code += " \n"
service_code += " // 计算响应时间\n"
service_code += " const responseTime = (Date.now() - startTime) / 1000;\n"
service_code += " \n"
service_code += " // 构建响应\n"
service_code += " const response = {\n"
service_code += " success: true,\n"
service_code += " result: result,\n"
service_code += " response_time: responseTime.toFixed(4),\n"
service_code += " message: '算法执行成功'\n"
service_code += " };\n"
service_code += " \n"
service_code += " // 发送响应\n"
service_code += " res.writeHead(200);\n"
service_code += " res.end(JSON.stringify(response));\n"
service_code += " } catch (e) {\n"
service_code += " // 构建错误响应\n"
service_code += " const errorResponse = {\n"
service_code += " success: false,\n"
service_code += " error: e.message,\n"
service_code += " message: '算法执行失败'\n"
service_code += " };\n"
service_code += " \n"
service_code += " // 发送错误响应\n"
service_code += " res.writeHead(400);\n"
service_code += " res.end(JSON.stringify(errorResponse));\n"
service_code += " }\n"
service_code += " });\n"
service_code += " } else {\n"
service_code += " // 不支持的方法\n"
service_code += " res.writeHead(405);\n"
service_code += " res.end(JSON.stringify({ error: 'Method Not Allowed' }));\n"
service_code += " }\n"
service_code += "}\n"
service_code += "\n"
service_code += "/**\n"
service_code += " * 启动服务\n"
service_code += " */\n"
service_code += "function startServer() {\n"
service_code += " const server = http.createServer(handleRequest);\n"
service_code += " \n"
service_code += " server.listen(PORT, HOST, () => {\n"
service_code += " console.log(`服务启动成功,监听地址: ${HOST}:${PORT}`);\n"
service_code += " console.log(`健康检查地址: http://${HOST}:${PORT}/health`);\n"
service_code += " console.log(`服务信息地址: http://${HOST}:${PORT}/info`);\n"
service_code += " });\n"
service_code += " \n"
service_code += " server.on('error', (error) => {\n"
service_code += " console.error('服务启动失败:', error);\n"
service_code += " });\n"
service_code += "}\n"
service_code += "\n"
service_code += "// 启动服务\n"
service_code += "startServer();\n"
# 替换模板变量
service_code = service_code.replace("{{entry_point}}", project_info.get("entry_point", ""))
service_code = service_code.replace("{{port}}", str(service_config.get("port", 8000)))
service_code = service_code.replace("{{timeout}}", str(service_config.get("timeout", 30)))
service_code = service_code.replace("{{name}}", service_config.get("name", "algorithm-service"))
service_code = service_code.replace("{{version}}", service_config.get("version", "1.0.0"))
return service_code
def _create_default_templates(self, template_dir: str):
"""创建默认模板
Args:
template_dir: 模板目录
"""
# 创建Python HTTP服务模板
python_http_template = '''
# 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:
# 根据入口点导入算法
if "{{entry_point}}" == "":
# 尝试导入主要模块
import algorithm
algorithm_module = algorithm
else:
# 动态导入入口点
import importlib.util
spec = importlib.util.spec_from_file_location("algorithm_module", "{{entry_point}}")
algorithm_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(algorithm_module)
print("算法模块导入成功")
except Exception as e:
print(f"算法模块导入失败: {e}")
algorithm_module = None
# 服务配置
HOST = os.environ.get("HOST", "{{host}}")
PORT = int(os.environ.get("PORT", "{{port}}"))
TIMEOUT = int(os.environ.get("TIMEOUT", "{{timeout}}"))
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_check_path}}":
# 健康检查
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": "{{project_name}}"}).encode('utf-8'))
def _handle_info(self):
"""处理服务信息请求"""
info = {
"service": "{{project_name}}",
"version": "1.0.0",
"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_check_path}}")
print(f"服务信息地址: http://{HOST}:{PORT}/info")
try:
server.serve_forever()
except KeyboardInterrupt:
print("服务停止")
server.shutdown()
if __name__ == "__main__":
run_server()
'''
with open(os.path.join(template_dir, "python_http_service.py.j2"), "w") as f:
f.write(python_http_template)
# 创建Node.js HTTP服务模板
nodejs_http_template = '''
// Node.js HTTP服务包装器
const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');
// 服务配置
const HOST = process.env.HOST || '{{host}}';
const PORT = process.env.PORT || {{port}};
const TIMEOUT = process.env.TIMEOUT || {{timeout}};
// 尝试导入算法模块
let algorithmModule = null;
try {
// 根据入口点导入算法
if ("{{entry_point}}" === "") {
// 尝试导入主要模块
algorithmModule = require('./algorithm');
} else {
// 导入入口点
algorithmModule = require('./{{entry_point}}');
}
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_check_path}}") {
// 健康检查
res.writeHead(200);
res.end(JSON.stringify({ status: 'healthy', service: '{{project_name}}' }));
} else if (pathname === '/info') {
// 服务信息
const info = {
service: '{{project_name}}',
version: '1.0.0',
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_check_path}}`);
console.log(`服务信息地址: http://${HOST}:${PORT}/info`);
});
server.on('error', (error) => {
console.error('服务启动失败:', error);
});
}
// 启动服务
startServer();
'''
with open(os.path.join(template_dir, "nodejs_http_service.js.j2"), "w") as f:
f.write(nodejs_http_template)