gunicorn部署下如何限制Polars线程数?求线程日志方法
问题描述
我用gunicorn+supervisor部署的应用里,Polars似乎占用了全部线程。请问限制Polars线程数的最佳方式是什么?(注:我并未进行CSV读写,示例代码仅作演示)另外,有没有办法实时记录Polars的线程占用数量?
相关代码文件
polars_script.py
import polars as pl df = pl.read_csv("input.csv") # Perform some basic operations df = df.filter(pl.col("column_name") > 50) # Filter rows where 'column_name' > 50 df = df.with_column((pl.col("column_name") * 2).alias("new_column")) # Add a new column # Write the DataFrame to a new CSV file df.write_csv("output.csv") print("Data processing complete. Output saved to output.csv")
app.py
from flask import Flask import polars as pl app = Flask(__name__) @app.route('/process') def process_data(): # Read a CSV file into a Polars DataFrame df = pl.read_csv("input.csv") # Perform some basic operations df = df.filter(pl.col("column_name") > 50) # Filter rows where 'column_name' > 50 df = df.with_column((pl.col("column_name") * 2).alias("new_column")) # Add a new column # Write the DataFrame to a new CSV file df.write_csv("output.csv") return "Data processing complete. Output saved to output.csv" if __name__ == "__main__": app.run()
gunicorn_config.py
bind = "0.0.0.0:8000" workers = 20
启动命令:gunicorn -c gunicorn_config.py app:app
解决方案
一、限制Polars线程数的最佳方式
Polars默认会占用机器全部CPU核心并行处理,再加上你设置的20个gunicorn worker,极易导致线程耗尽。以下是几种可靠的限制方案:
1. 全局环境变量设置(推荐)
通过POLARS_MAX_THREADS环境变量全局限制线程数,适配supervisor部署场景:
- 修改supervisor配置文件,在启动命令前注入环境变量:
[program:your-app] command=/path/to/venv/bin/gunicorn -c gunicorn_config.py app:app environment=POLARS_MAX_THREADS=4 - 或者在
gunicorn_config.py中通过raw_env指定:
每个gunicorn worker都会继承该变量,限制单个worker内Polars的线程数。bind = "0.0.0.0:8000" workers = 20 raw_env = ["POLARS_MAX_THREADS=4"]
2. 代码内动态设置
如果需要针对不同任务灵活调整线程数,可在代码中直接设置:
import polars as pl # 在Polars操作前初始化线程数 pl.set_threads(4) # 后续所有Polars操作都会使用指定线程数 df = pl.read_csv("input.csv") # ...其他数据处理逻辑
该设置为进程全局生效,建议在应用初始化时调用一次。
3. 配合gunicorn worker数调整
当前20个worker的配置如果搭配Polars默认线程数,会远超机器负载。建议根据机器核心数调整worker数(比如8核机器设8-12个worker),再结合Polars线程限制,避免资源过载。
二、实时记录Polars线程占用数量
1. 代码内直接获取
Polars提供get_threads()方法,可在关键节点记录线程数:
import polars as pl import logging # 配置日志输出 logging.basicConfig(level=logging.INFO) @app.route('/process') def process_data(): # 记录初始线程数 logging.info(f"Polars current threads: {pl.get_threads()}") df = pl.read_csv("input.csv") df = df.filter(pl.col("column_name") > 50) df = df.with_column((pl.col("column_name") * 2).alias("new_column")) # 记录处理过程中的线程数 logging.info(f"Polars threads during processing: {pl.get_threads()}") df.write_csv("output.csv") return "Data processing complete. Output saved to output.csv"
2. 系统层面监控
如果需要更全面的进程线程监控,可使用系统工具:
- 用
htop查看:找到gunicorn worker进程,THR列的数值即为该进程的总线程数(包含Polars使用的线程)。 - 用
ps命令统计:ps -o nlwp <pid>,替换<pid>为gunicorn worker的进程ID,nlwp表示线程数。
内容的提问来源于stack exchange,提问作者r ram
相关产品推荐
相关产品推荐

