978 lines
40 KiB
Python
978 lines
40 KiB
Python
"""服务生成器,用于生成算法服务包装器"""
|
||
|
||
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)
|