Refactor service deployment to use direct process execution
- Remove bash wrapper script - Update systemd service configuration - Improve process management for gunicorn - Simplify shared storage cleanup logic - Update documentation for deployment
This commit is contained in:
parent
6489aaa7f0
commit
d5bcd14c6f
8 changed files with 40 additions and 53 deletions
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source /home/netman/lightrag-xyj/venv/bin/activate
|
||||
lightrag-server
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=LightRAG XYJ Ollama Service
|
||||
Description=LightRAG XYJ Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
|
|
@ -8,10 +8,20 @@ User=netman
|
|||
# Memory settings
|
||||
MemoryHigh=8G
|
||||
MemoryMax=12G
|
||||
|
||||
# Using virtual enviroment created by miniconda
|
||||
Environment="PATH=/home/netman/miniconda3/bin:/home/netman/lightrag-xyj/venv/bin"
|
||||
WorkingDirectory=/home/netman/lightrag-xyj
|
||||
ExecStart=/home/netman/lightrag-xyj/lightrag-api
|
||||
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
|
||||
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
|
||||
|
||||
# Kill mode require ExecStart must be gunicorn or unvicorn main process
|
||||
KillMode=process
|
||||
ExecStop=/bin/kill -s TERM $MAINPID
|
||||
TimeoutStopSec=60
|
||||
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
RestartSec=30
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -184,24 +184,16 @@ MAX_ASYNC=4
|
|||
|
||||
### 将 Lightrag 安装为 Linux 服务
|
||||
|
||||
从示例文件 `lightrag.service.example` 创建您的服务文件 `lightrag.service`。修改服务文件中的 WorkingDirectory 和 ExecStart:
|
||||
从示例文件 `lightrag.service.example` 创建您的服务文件 `lightrag.service`。修改服务文件中的服务启动定义:
|
||||
|
||||
```text
|
||||
Description=LightRAG Ollama Service
|
||||
WorkingDirectory=<lightrag 安装目录>
|
||||
ExecStart=<lightrag 安装目录>/lightrag/api/lightrag-api
|
||||
```
|
||||
|
||||
修改您的服务启动脚本:`lightrag-api`。根据需要更改 python 虚拟环境激活命令:
|
||||
|
||||
```shell
|
||||
#!/bin/bash
|
||||
|
||||
# 您的 python 虚拟环境激活命令
|
||||
source /home/netman/lightrag-xyj/venv/bin/activate
|
||||
# 启动 lightrag api 服务器
|
||||
lightrag-server
|
||||
# Set Enviroment to your Python virtual enviroment
|
||||
Environment="PATH=/home/netman/lightrag-xyj/venv/bin"
|
||||
WorkingDirectory=/home/netman/lightrag-xyj
|
||||
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
|
||||
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
|
||||
```
|
||||
> ExecStart命令必须是 lightrag-gunicorn 或 lightrag-server 中的一个,不能使用其它脚本包裹它们。因为停止服务必须要求主进程必须是这两个进程。
|
||||
|
||||
安装 LightRAG 服务。如果您的系统是 Ubuntu,以下命令将生效:
|
||||
|
||||
|
|
|
|||
|
|
@ -188,24 +188,18 @@ MAX_ASYNC=4
|
|||
|
||||
### Install LightRAG as a Linux Service
|
||||
|
||||
Create your service file `lightrag.service` from the sample file: `lightrag.service.example`. Modify the `WorkingDirectory` and `ExecStart` in the service file:
|
||||
Create your service file `lightrag.service` from the sample file: `lightrag.service.example`. Modify the start options the service file:
|
||||
|
||||
```text
|
||||
Description=LightRAG Ollama Service
|
||||
WorkingDirectory=<lightrag installed directory>
|
||||
ExecStart=<lightrag installed directory>/lightrag/api/lightrag-api
|
||||
# Set Enviroment to your Python virtual enviroment
|
||||
Environment="PATH=/home/netman/lightrag-xyj/venv/bin"
|
||||
WorkingDirectory=/home/netman/lightrag-xyj
|
||||
# ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-server
|
||||
ExecStart=/home/netman/lightrag-xyj/venv/bin/lightrag-gunicorn
|
||||
|
||||
```
|
||||
|
||||
Modify your service startup script: `lightrag-api`. Change your Python virtual environment activation command as needed:
|
||||
|
||||
```shell
|
||||
#!/bin/bash
|
||||
|
||||
# your python virtual environment activation
|
||||
source /home/netman/lightrag-xyj/venv/bin/activate
|
||||
# start lightrag api server
|
||||
lightrag-server
|
||||
```
|
||||
> The ExecStart command must be either `lightrag-gunicorn` or `lightrag-server`; no wrapper scripts are allowed. This is because service termination requires the main process to be one of these two executables.
|
||||
|
||||
Install LightRAG service. If your system is Ubuntu, the following commands will work:
|
||||
|
||||
|
|
|
|||
|
|
@ -129,11 +129,13 @@ def on_exit(server):
|
|||
print("=" * 80)
|
||||
print("GUNICORN MASTER PROCESS: Shutting down")
|
||||
print(f"Process ID: {os.getpid()}")
|
||||
print("=" * 80)
|
||||
|
||||
# Release shared resources
|
||||
print("Finalizing shared storage...")
|
||||
finalize_share_data()
|
||||
|
||||
print("Gunicorn shutdown complete")
|
||||
print("=" * 80)
|
||||
|
||||
print("=" * 80)
|
||||
print("Gunicorn shutdown complete")
|
||||
print("=" * 80)
|
||||
|
|
|
|||
|
|
@ -326,15 +326,14 @@ def create_app(args):
|
|||
# Clean up database connections
|
||||
await rag.finalize_storages()
|
||||
|
||||
# In Gunicorn mode with preload_app=True, cleanup is handled by worker_exit/on_exit hooks
|
||||
# Only perform cleanup in Uvicorn single-process mode
|
||||
if "LIGHTRAG_GUNICORN_MODE" not in os.environ:
|
||||
# Clean up shared data
|
||||
logger.debug("Unvicorn Mode: finalize shared storage...")
|
||||
# Only perform cleanup in Uvicorn single-process mode
|
||||
logger.debug("Unvicorn Mode: finalizing shared storage...")
|
||||
finalize_share_data()
|
||||
else:
|
||||
# In Gunicorn mode with preload_app=True, cleanup is handled by on_exit hooks
|
||||
logger.debug(
|
||||
"Gunicorn Mode: don not finalize shared storage in worker process"
|
||||
"Gunicorn Mode: postpone shared storage finalization to master process"
|
||||
)
|
||||
|
||||
# Initialize FastAPI
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@ def main():
|
|||
check_and_install_dependencies()
|
||||
|
||||
# Note: Signal handlers are NOT registered here because:
|
||||
# - Worker cleanup is handled by gunicorn_config.worker_exit()
|
||||
# - Master cleanup is handled by gunicorn_config.on_exit()
|
||||
# This prevents race conditions when multiple processes try to finalize shared data
|
||||
# - Master cleanup already handled by gunicorn_config.on_exit()
|
||||
|
||||
# Display startup information
|
||||
display_splash_screen(global_args)
|
||||
|
|
|
|||
|
|
@ -1444,7 +1444,7 @@ async def get_namespace_data(
|
|||
return _shared_dicts[namespace]
|
||||
|
||||
|
||||
def finalize_share_data(shutdown_manager: bool = True):
|
||||
def finalize_share_data():
|
||||
"""
|
||||
Release shared resources and clean up.
|
||||
|
||||
|
|
@ -1453,10 +1453,6 @@ def finalize_share_data(shutdown_manager: bool = True):
|
|||
|
||||
In multi-process mode, it shuts down the Manager and releases all shared objects.
|
||||
In single-process mode, it simply resets the global variables.
|
||||
|
||||
Args:
|
||||
shutdown_manager: If True, shut down the multiprocessing Manager.
|
||||
Should be True only for the main process, False for worker processes.
|
||||
"""
|
||||
global \
|
||||
_manager, \
|
||||
|
|
@ -1483,8 +1479,8 @@ def finalize_share_data(shutdown_manager: bool = True):
|
|||
f"Process {os.getpid()} finalizing storage data (multiprocess={_is_multiprocess})"
|
||||
)
|
||||
|
||||
# In multi-process mode, shut down the Manager only if requested
|
||||
if _is_multiprocess and _manager is not None and shutdown_manager:
|
||||
# In multi-process mode, shut down the Manager
|
||||
if _is_multiprocess and _manager is not None:
|
||||
try:
|
||||
# Clear shared resources before shutting down Manager
|
||||
if _shared_dicts is not None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue