Browse Source

框架搭建

zhangnaiwen 1 year ago
parent
commit
564866e451

+ 10 - 0
.idea/tile_conversion_server.iml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="jdk" jdkName="Python 3.11 (tile_conversion)" jdkType="Python SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
Dockerfile

@@ -0,0 +1,6 @@
+FROM operation_management_center_base:1.0.0
+
+COPY ./conf/uwsgi.ini /work/operation_management_center/conf/uwsgi.ini
+COPY ./src /work/operation_management_center/src
+
+WORKDIR /work/operation_management_center/src

+ 31 - 0
base/Dockerfile

@@ -0,0 +1,31 @@
+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
+
+
+RUN apt-get -y update \
+    && apt-get -y upgrade \
+    && apt-get install -y supervisor libpq-dev python3-dev\
+    && pip3 install -r /tmp/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple \
+    && pip3 install uwsgi -i https://pypi.tuna.tsinghua.edu.cn/simple \
+    # 默认是128,当server处理请求较慢,以至于socket监听队列被填满后,新来的请求会被拒绝。
+    && mkdir /opt/init  \
+    && echo "echo 2048 > /proc/sys/net/core/somaxconn" > /opt/init/sysctl.sh  \
+    && chmod +x /opt/bootstrap.sh \
+    # 清理和删除工作
+    && apt-get autoremove -y  \
+    && apt-get autoclean -y \
+    && apt-get clean -y \
+    && rm -rf /tmp/* /var/tmp/*  \
+    && find /var/cache/apt/archives /var/lib/apt/lists -not -name lock -type f -delete  \
+    && find /var/cache -type f -delete \
+    && find /var/log -type f | while read f; do echo -n '' > ${f}; done \
+    && rm -rf /var/lib/apt/lists/* \
+    && rm -rf ~/.cache/pip/*
+
+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

+ 34 - 0
config/config.yml

@@ -0,0 +1,34 @@
+common:
+  JWT_SECRET: SKYversation0816
+  JWT_EXPIRY: 86400
+  MESSAGR_TYPE: ["普通消息","提醒消息"]
+  INFORMATION_TYPE: ["楼层地图信息配置", "安保人员信息配置"]
+
+  SAVE_FILE_PATH: /data/files
+  FILE_URL: http://127.0.0.1/
+
+RabbitMq:
+  HOST: 8.130.177.22 # ip地址
+  POST: 5672 # 端口
+  USER: admin # 用户名
+  PASSWORD: aaaaaa  # 密码
+  QUEUE: message # 队列
+
+system_monitoring:
+  HOST: 121.43.55.7 # ip地址
+  POST: 2024 # 端口
+
+#redis:
+#  # redis配置
+#  HOST: 192.168.2.35 # 使用容器运行服务时,该HOST信息无用,容器内部会自动获取redis容器的ip
+#  PORT: 6379 # 不要修改该端口号,除非明确了解使用场景
+#  DB: 0
+
+database:
+  # 数据库配置信息
+  # 如果使用外部数据库,例如polardb,请修改以下配置信息
+  HOST: 121.43.55.7 # 数据库IP地址
+  PORT: 5433 # 数据库端口号
+  USER: postgres # 用户名
+  PASSWORD: SKYversation@0816  # 密码
+  DB: building # 数据库名

+ 27 - 0
docker-compose-v3.yml

@@ -0,0 +1,27 @@
+version: '3'
+services:
+  sky-gistools-server:
+      container_name: operation_management_center
+
+      image: operation_management_center:1.0.0
+
+      ports:
+        - "5000:5000"
+
+      environment:
+        - UWSGI_PROCESSES=8
+        - UWSGI_ENABLE_THREADS=true
+        - UWSGI_HTTP_PROCESSES=4
+        - UWSGI_HTTP_KEEPALIVE=false
+        - UWSGI_HARAKIRI=600
+        - UWSGI_TIMEOUT=600
+        - UWSGI_PY_OPTIMIZE=0
+
+      volumes:
+        - /data/logs:/data/logs # 日志
+        - /data/files:/data/files
+        - ./config:/work/operation_management_center/config  # 配置文件目录,包括软件配置信息
+
+      privileged: true
+
+      restart: always

+ 26 - 0
docker-compose.yml

@@ -0,0 +1,26 @@
+service:
+  container_name: operation_management_center
+
+  image: operation_management_center:1.0.0
+
+  ports:
+    - "5000:5000"
+
+  environment:
+    - UWSGI_PROCESSES=8
+    - UWSGI_ENABLE_THREADS=true
+    - UWSGI_HTTP_PROCESSES=4
+    - UWSGI_HTTP_KEEPALIVE=false
+    - UWSGI_HARAKIRI=600
+    - UWSGI_TIMEOUT=600
+    - UWSGI_PY_OPTIMIZE=0
+
+  volumes:
+    - /data/logs:/data/logs # 日志
+    - /data/files:/data/files # 文件保存地址
+    - ./config:/work/operation_management_center/config  # 配置文件目录,包括软件配置信息
+
+
+  privileged: true
+
+  restart: always

+ 0 - 0
requirements.txt


+ 4 - 0
scripts/built.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+docker build -f base/Dockerfile -t operation_management_center_base:1.0.0 .
+docker build -t operation_management_center:1.0.0 .

+ 3 - 0
scripts/init_db.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+docker exec -it operation_management_center  bash -c "export PYTHONPATH=/work/operation_management_center/src;export FLASK_APP=manage.py;flask dbinit"

+ 0 - 0
src/__init__.py


+ 40 - 0
src/app/__init__.py

@@ -0,0 +1,40 @@
+import os
+from urllib import parse
+
+from flask import Flask
+# from flask_apscheduler import APScheduler
+from flask_cors import CORS
+
+# from sqlalchemy import create_engine
+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)
+
+    # url = f'postgresql+psycopg2://{config.database.USER}:{parse.quote(config.database.PASSWORD)}@{config.database.HOST}:{config.database.PORT}/{config.database.DB}'
+    # app.engine = create_engine(url)
+
+    api.init_app(app)
+
+    # app.scheduler = APScheduler()
+    # app.scheduler.init_app(app)
+    # app.scheduler.start()
+
+    return app

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

@@ -0,0 +1,5 @@
+from flask_restx import Api
+
+api = Api(version='v1.0', title='', description='', doc='/api')
+
+# api.add_namespace()

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

@@ -0,0 +1,6 @@
+class StatesCode:
+    SUCCESS = 0  # 成功
+    UNKNOWN_ERROR = -1  # 未知错误
+    PARA_MISSING = -2  # 参数缺失
+    PARA_ERROR = -3  # 参数错误
+

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


+ 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"