zhangnaiwen 1 an în urmă
părinte
comite
847f7c44f6

+ 11 - 0
base/Dockerfile

@@ -0,0 +1,11 @@
+FROM debian11_py3.9_slim:latest
+
+COPY ./requirements.txt /tmp/
+COPY ./conf/bootstrap.sh /opt/bootstrap.sh
+COPY ./conf/supervisord.conf /etc/
+COPY ./conf/supervisor.conf /etc/supervisord.d/supervisor.conf
+
+
+ENTRYPOINT ["/opt/bootstrap.sh"]
+
+EXPOSE 5000

+ 47 - 0
conf/bootstrap.sh

@@ -0,0 +1,47 @@
+#!/bin/bash
+
+set -e
+set -u
+
+# supervisord 配置文件
+SUPERVISOR_PARAMS='-c /etc/supervisord.conf'
+
+
+# 创建一些需要的目录
+mkdir -p /data/conf /data/run /data/logs/
+chmod 711 /data/conf /data/run /data/logs
+
+#export WORKER_REDIS_PORT=${REDIS_PORT:6}
+#export WORKER_REDIS_DB=${REDIS_DB:-0}
+
+# 遍历 `/opt/init/*.sh`,然后执行它
+if [ "$(ls /opt/init/)" ]; then
+  for cmd in /opt/init/*.sh; do
+    . $cmd
+  done
+fi
+
+
+# 可能会使用一个交互式的容器.
+if test -t 0; then
+  # 运行 supervisord 到后台
+  supervisord $SUPERVISOR_PARAMS
+
+  # 运行一些命令并退出
+  # 没有命令时,运行bash
+  if [[ $@ ]]; then
+    eval $@
+  else
+    export PS1='[\u@\h : \w]\$ '
+    /bin/bash
+  fi
+
+# 运行 supervisord 在前台, 保持直到停止容器.
+else
+  # 有额外的参数,先执行它.
+  # 可能会有些问题
+  if [[ $@ ]]; then
+    eval $@
+  fi
+  supervisord -n $SUPERVISOR_PARAMS
+fi

+ 8 - 0
conf/supervisor.conf

@@ -0,0 +1,8 @@
+[program:operation_management_center]
+command = uwsgi /work/operation_management_center/conf/uwsgi.ini
+
+autorestart = true
+redirect_stderr = true
+stopsignal = QUIT
+stderr_logfile = /data/logs/operation_management_center_error.log
+stdout_logfile = /data/logs/operation_management_center.log

+ 18 - 0
conf/supervisord.conf

@@ -0,0 +1,18 @@
+[supervisord]
+pidfile = /run/supervisord.pid
+logfile = /data/logs/supervisord.log
+# Set loglevel=debug, only then all logs from child services are printed out
+# to container logs (and thus available via `docker logs [container]
+loglevel = debug
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[inet_http_server]
+port:127.0.0.1:9999
+
+[supervisorctl]
+serverurl=http://127.0.0.1:9999
+
+[include]
+files = /etc/supervisord.d/*.conf

+ 131 - 0
conf/uwsgi.ini

@@ -0,0 +1,131 @@
+[uwsgi]
+# 指定应用的用户(组)
+if-env = UWSGI_USER
+uid = $(UWSGI_USER)
+endif =
+
+if-env = UWSGI_GROUP
+gid = $(UWSGI_GROUP)
+endif =
+
+# 监听的ip与端口
+http = :5000
+if-env = UWSGI_HTTP
+http = $(UWSGI_HTTP)
+endif =
+
+# PID文件
+pidfile = /var/run/operation_management_center.pid
+
+# 主入口模块
+module = app.webapp
+
+# 主入口函数
+callable = application
+
+# 需要关闭master,否则会导致进程中使用全局变量会出错
+master = true
+
+# 这个会导致不正常,待测试
+#async=128
+
+# 进程数
+processes = 2
+if-env = UWSGI_PROCESSES
+processes = $(UWSGI_PROCESSES)
+endif =
+
+# 运行多线程
+enable-threads = 0
+if-env = UWSGI_ENABLE_THREADS
+enable-threads = $(UWSGI_ENABLE_THREADS)
+endif =
+
+# http的线程数
+http-processes = 2
+if-env = UWSGI_HTTP_PROCESSES
+http-processes = $(UWSGI_HTTP_PROCESSES)
+endif =
+
+# 是否保持http连接
+http-keepalive = 0
+if-env = UWSGI_HTTP_KEEPALIVE
+http-keepalive = $(UWSGI_HTTP_KEEPALIVE)
+endif =
+
+# 超时关闭连接的时间(秒)
+harakiri = 20
+if-env = UWSGI_HARAKIRI
+harakiri = $(UWSGI_HARAKIRI)
+endif =
+
+# 连接时间
+http-timeout = 60
+if-env = UWSGI_TIMEOUT
+http-timeout = $(UWSGI_TIMEOUT)
+endif =
+
+# 打开http body缓冲
+if-env = UWSGI_POST_BUFFERING
+post-buffering = $(UWSGI_POST_BUFFERING)
+endif =
+
+# python解释器的优化,=0不优化
+if-env = UWSGI_PY_OPTIMIZE
+optimize = $(UWSGI_PY_OPTIMIZE)
+endif =
+
+# 关闭http请求的日志
+if-env = UWSGI_DISABLE_LOGGING
+disable-logging = $(UWSGI_DISABLE_LOGGING)
+endif =
+
+# 记录uwsgi自身的日志
+logto = /data/logs/operation_management_center.log
+# daemonize = /data/logs/nginx_agent.log
+
+
+# 等待其它进程重启(直到接收到的请求处理完才重启)/关闭的最大时间(秒)
+reload-mercy = 2
+
+# CPU亲和性
+cpu-affinity = 1
+
+# 进程的内存限制(address space/vsz)
+if-env = UWSGI_LIMIT_AS
+limit-as = $(UWSGI_LIMIT_AS)
+endif =
+
+# 占用内存(address space)大于指定值(MB),重启服务
+if-env = UWSGI_RELOAD_ON_AS
+reload-on-as = $(UWSGI_RELOAD_ON_AS)
+endif =
+
+# 占用内存(rss)大于指定值(MB),重启服务
+if-env = UWSGI_RELOAD_ON_RSS
+reload-on-rss = $(UWSGI_RELOAD_ON_RSS)
+endif =
+
+# 超过指定请求数,会创建新的进程
+if-env = UWSGI_MAX_REQUESTS
+max-requests = $(UWSGI_MAX_REQUESTS)
+endif =
+
+# 退出时清除环境(自动删除unix socket文件和pid文件)
+vacuum = true
+
+# python代码变化后自动重启服务,仅用用开发环境
+if-env = UWSGI_PY_AUTORELOAD
+py-autoreload = $(UWSGI_PY_AUTORELOAD)
+endif =
+
+# master进程关闭会自动杀死workers
+no-orphans = true
+
+# 设置socket的监听队列大小
+if-env = UWSGI_LISTEN
+listen = $(UWSGI_LISTEN)
+endif =
+
+# python包环境
+pythonpath=/work/operation_management_center/src

+ 18 - 0
config/config.yml

@@ -0,0 +1,18 @@
+common:
+  CACHE_PATH: /Users/mac/data/cache
+  OUTPUT_PATH:  /Users/mac/data/output
+
+redis:
+  # redis配置
+  HOST: 127.0.0.1 # 使用容器运行服务时,该HOST信息无用,容器内部会自动获取redis容器的ip
+  PORT: 6379 # 不要修改该端口号,除非明确了解使用场景
+  DB: 0
+
+#database:
+#  # 数据库配置信息
+#  # 如果使用外部数据库,例如polardb,请修改以下配置信息
+#  HOST: 121.43.55.7 # 数据库IP地址
+#  PORT: 5433 # 数据库端口号
+#  USER: postgres # 用户名
+#  PASSWORD: SKYversation@0816  # 密码
+#  DB: building # 数据库名

+ 0 - 0
src/__init__.py


+ 31 - 0
src/app/__init__.py

@@ -0,0 +1,31 @@
+import os
+from urllib import parse
+
+from flask import Flask
+from flask_cors import CORS
+
+from app.api import api
+from app.helpers import request_handlers
+from config import Config
+
+manage_path = os.path.dirname(os.path.abspath(__file__))
+config_yml_path = os.path.join(os.path.dirname(os.path.dirname(manage_path)), 'config', 'config.yml')
+
+
+def create_app():
+    """创建app并初始化相关配置参数"""
+
+    config = Config()
+    config.load(config_yml_path)
+
+    app = Flask(__name__)
+
+    # app.config.from_object()
+
+    CORS(app)
+
+    # request_handlers.configure(app)
+
+    api.init_app(app)
+
+    return app

+ 7 - 0
src/app/api/__init__.py

@@ -0,0 +1,7 @@
+from flask_restx import Api
+
+from app.api.mission import ns
+
+api = Api(version='v1.0', title='', description='', doc='/api')
+
+api.add_namespace(ns)

+ 21 - 0
src/app/defines/__init__.py

@@ -0,0 +1,21 @@
+class StatesCode:
+    UNKNOWN_ERROR = -2  # 未知错误
+    SUCCESS = 0  # 成功
+    PARA_MISSING = 10  # 参数缺失
+    NO_DATA = 11  # 数据不存在
+    MISSION_TYPE_EOORE = 12  # 产品类型错误
+    PARA_ERROR = 13  # 参数错误
+    DATA_ERROR = 14  # 数据错误
+    QUEUE_NOT_EXIST = 101  # 队列不存在
+    JOB_NOT_EXIST = 102  # 任务不存在
+    JOB_STATUS_NO_EXIST = 103  # 任务状态不存在
+    NOT_SUPPORT = 104  # 任务类型不支持
+    JOB_ERROR = 105  # 任务错误
+
+
+class TILE_GRID_TYPE:
+    GoogleEarthQuad = "GoogleEarthQuad"
+    WGS1984Quad     = "WGS1984Quad"
+    WebMercatorQuad = "WebMercatorQuad"
+
+    ALL = [GoogleEarthQuad, WGS1984Quad, WebMercatorQuad, ]

+ 0 - 0
src/app/helpers/__init__.py


+ 11 - 0
src/app/helpers/request_handlers.py

@@ -0,0 +1,11 @@
+from flask import request, g, jsonify
+
+
+def configure(app):
+    @app.before_request
+    def authenticate():
+        """
+        这里验证token
+        :return:
+        """
+        pass

+ 5 - 0
src/app/modle/__init__.py

@@ -0,0 +1,5 @@
+from sqlalchemy.orm import DeclarativeBase
+
+
+class Base(DeclarativeBase):
+    pass

+ 0 - 0
src/app/utils/__init__.py


+ 6 - 0
src/app/webapp.py

@@ -0,0 +1,6 @@
+from app import create_app
+
+application = create_app()
+
+if __name__ == '__main__':
+    application.run(host="0.0.0.0", debug=True)

+ 50 - 0
src/config.py

@@ -0,0 +1,50 @@
+import yaml
+
+
+class Object(dict):
+
+    def __init__(self):
+
+        super(Object, self).__init__()
+
+    def __getattr__(self, key):
+
+        return self.get(key)
+
+    def __setattr__(self, key, value):
+
+        if isinstance(value, dict):
+
+            o = Object()
+
+            o.set(value)
+
+            self[key] = o
+
+        else:
+
+            self[key] = value
+
+    def set(self, dictionary, clear=False):
+
+        if clear:
+            self.clear()
+
+        for key, value in dictionary.items():
+            self.__setattr__(key, value)
+
+
+class Config(Object):
+    _instance = None
+
+    def __new__(cls, *args, **kwargs):
+        if Config._instance is None:
+            Config._instance = super().__new__(cls)
+
+        return Config._instance
+
+    def load(self, filename):
+        with open(filename, 'r', encoding='utf8') as stream:
+            data = yaml.load(stream, Loader=yaml.FullLoader)
+
+            self.set(data)

+ 43 - 0
src/manage.py

@@ -0,0 +1,43 @@
+from urllib import parse
+
+from flask import current_app
+from sqlalchemy import create_engine, insert
+from sqlalchemy.orm import Session
+from sqlalchemy_utils import database_exists, create_database
+
+from app import Config
+from app.modle import Base
+from app.modle.users import User
+from app.webapp import application
+
+
+@application.cli.command('dbinit')
+def dbinit():
+    """初始化数据库,存入任务模板参数"""
+
+    print('initialize db ...')
+
+    config = Config()
+
+    uri = f'postgresql+psycopg2://{config.database.USER}:{parse.quote(config.database.PASSWORD)}@{config.database.HOST}:{config.database.PORT}/{config.database.DB}'
+
+    engine = create_engine(uri)
+
+    # 判断数据库是否存在,如果不存在则创建一个
+    if not database_exists(engine.url):
+        create_database(engine.url)
+
+    Base.metadata.create_all(engine)
+
+    print('initialize db ok ...\n')
+
+    print('Please Enter Ctrl+C to exit ...')
+
+
+@application.cli.command('ceshi')
+def ceshi():
+    print('this is a test')
+
+
+if __name__ == '__main__':
+    dbinit()

+ 4 - 0
src/version.py

@@ -0,0 +1,4 @@
+# VERSION = "1.0.1r"
+# PROJECT_NAME = "sky-gistools-server"
+# DESCRIPTION = "gis多算法、坐标转换、几何检索等功能"
+# RELEASE_TIME = "2023-03-2 16:35:03"