4.3 worker_thread从postgres取数据并发

Python异步并发实战:用asyncio突破I/O瓶颈 在Web服务与数据管道中,I/O密集型任务(如数据库查询、HTTP调用、消息收发)常成为吞吐瓶颈——同步阻塞模型导致CPU空转、资源利用率低下。asyncio通过单线程事件循环与协程机制,在系统调用释放GIL的间隙高效复用执行单元,实现高并发低开销。其核心价值在于不依赖多进程扩容,即可显著提升QPS、降低内存占用,并天然支持超时控制、信号量限流与生产者-消费者解耦。本文聚焦Python应用层并发优化,覆盖asyncio与concurrent.futures的协同分工、真实库存服务迁移案例及高频线上问题排查, 阅读详情

1、数据库配置

config/config.js

exports.config = {
    options:{
        host: 'postgres-testdata.lan',
        port: 5432,
        user: 'kear',
        database: 'test',
        password: '123123',
    }
}

2、数据库连接并返回数据

api:https://node-postgres.com/api/pool/

utils/connect_database.js

const {config} = require('../config/config')
const { Pool } = require('pg')
const pool = new Pool(config.options)

/**
 * @description - This function is used to connect to the database
 * @param index - 需要单次返回的数据条数
 * @param offset - 数据偏移量
 * @returns {Promise<object>}
 */
function getData(index,offset){
    return new Promise((resolve,reject)=>{
        pool.connect( (err, client, release) => {
            if (err) throw err
            client.query(`SELECT * FROM "base-performance_1000w" offset ${offset} limit ${index}`,  (err, res) => {
                release();
                if (err) {
                    reject (err.stack)
                } else {
                    resolve (res.rows)
                }
            })
        })
    })
}
module.exports = getData

3、worker_thread/check/run.js

const {Worker} = require('worker_threads')
const getData = require('../../utils/connetct_database')
const thread_num = 100
const limit = 100//每次取数据条数
const large_limit = 10000000//大数据量取数据条数
const result_memory = new SharedArrayBuffer(32);
const result = new Int32Array(result_memory);
const memory_size = thread_num * 40000;
const share_memory = new SharedArrayBuffer(memory_size);
const thread_data = new Int16Array(share_memory);

async function performanceTest() {
    let result_data = {
        passTotal: 0,//断言通过的数量
        successTotal: 0,//请求成功数量
        count: 0,//重新取数据标记
        totalReq: 0,//总请求数
        maxData: 0,//最大数据量
        exceptionTotal: 0,//请求成功且断言正确的数量
        start_time: 0,//开始时间
        end_time: 0,//结束时间
    }
    for (let i = 0; i < 8; i++) {
        result[i] = 0
    }
    //根据线程数取数据
    for (let i = 0; i < thread_num; i++) {
        await getData(limit, limit * i).then(res => {
            //构造数据结构,绑定线程id
            let data = {
                id: i + 1,//线程id
                value: res
            }
            //将data转换成字符串
            let data_str = JSON.stringify(data);
            //将字符串转成unicode码并存储数据
            if (data_str.length >= (memory_size / 2)) {
                console.log('数据过大,超出内存空间');
            } else {
                for (let j = 0; j < data_str.length; j++) {
                    thread_data[i * (memory_size / (2 * thread_num)) + j] = data_str.charCodeAt(j);
                }
            }
        })
    }
    //创建工作线程
    for (let i = 0; i < thread_num; i++) {
        const worker = new Worker('./wechat_text.js');
        worker.postMessage({
            threadId: worker.threadId,
            data: thread_data,
            memory_size: memory_size,
            thread_num: thread_num,
            statistics: result,
        });
        worker.on('message', async (message) => {
            if (Atomics.load(result, 4) < large_limit) {
                let data = {
                    id: message.threadId,//线程id
                }
                let count = Atomics.load(result, 2);
                await getData(limit, (thread_num + count - 1) * limit).then(res => {
                    data.value = res
                })
                //将data转换成字符串
                let data_str = JSON.stringify(data);
                for (let j = (message.threadId - 1) * 20000; j < 20000 + (message.threadId - 1) * 20000; j++) {
                    // Atomics.store(thread_data, j, data_str.charCodeAt(j - (message.threadId-1) * 20000));
                    if (j < data_str.length) {
                        thread_data[j] = data_str.charCodeAt(j - (message.threadId - 1) * 20000);
                    } else {
                        thread_data[j] = "\0".charCodeAt(0);
                        break
                    }
                }
                worker.postMessage({
                    threadId: message.threadId,
                    data: thread_data,
                    memory_size: memory_size,
                    thread_num: thread_num,
                    statistics: result,
                })
            } else {
                worker.terminate().then(() => {
                })
            }
        })
    }
}

performanceTest().then(() => {
    console.log('正在启动')
}).catch(err => {
    console.log(err)
})
process.on('exit', () => {
    console.table({
        '运行时长': (Atomics.load(result, 7) - Atomics.load(result, 6)) / 1000 + "s",
        '工作线程': thread_num,
        '请求总数': Atomics.load(result, 3),
        '请求成功': Atomics.load(result, 1),
        '请求通过': Atomics.load(result, 0),
        '请求失败': Atomics.load(result, 5),
        '每秒并发': Math.floor(Atomics.load(result, 3) / ((Atomics.load(result, 7) - Atomics.load(result, 6)) / 1000))
    })
})

4、worker_thread/check/text.js

const {parentPort} = require('worker_threads');
const axios = require('axios');
let body = {
    id:"",
    data:{}
}

let config = {
    method: 'post',
    url: 'http://192.168.3.74:8002/api/inspect/v1/context',
    headers: {
        'Content-Type': 'application/json'
    },
    data: body,
    timeout: 10000
};
parentPort.on('message', async (message) => {
    let text = '';
    let tempId = '';
    for (let j = 0; j < message.thread_num; j++) {
        //i每次循环的初值分别是0,20000,40000等差数列,即每个线程存储数据所占用的40000byte,即20000个字符
        for (let i = j * message.memory_size / (2 * message.thread_num); i < (j + 1) * message.memory_size / (2 * message.thread_num); i++) {
            //存储结构中没有字符存入时,默认值是\0,如果遇到\0就跳出,说明已经达到字符串的末尾了,后续的字节就无需再取了
            if (String.fromCharCode(message.data[i]) === '\0') {
                break;
            } else {
                let temp_text = `"id":${message.threadId}`;
                //取前面10个字符,判断threadId是否相等,不相等则跳过,减少循环次数
                if (i === 9 && !new RegExp(temp_text).test(text)) {
                    text = '';
                    tempId = '';
                    break;
                } else {
                    tempId = message.threadId;
                    text += String.fromCharCode(message.data[i]);
                }
            }
        }
        if (text !== '') {
            break;
        }
    }
    if (text !== '') {
        let temp = JSON.parse(text);
        Atomics.add(message.statistics, 4, temp.value.length)
        for (let k of temp.value) {
            body['textContent'] = JSON.stringify(k);
            Atomics.add(message.statistics, 3, 1)
            if (Atomics.load(message.statistics, 6) === 0) {
                Atomics.store(message.statistics, 6, new Date().getTime())
            }
            console.log(Atomics.load(message.statistics, 3))
            await axios(config).then(res => {
                Atomics.add(message.statistics, 1, 1)
                if (res.data.data.result === "nopass") {
                    Atomics.add(message.statistics, 0, 1)
                }

            }).catch(err => {
                Atomics.add(message.statistics, 5, 1)
                console.log(err);
            })
        }
        Atomics.add(message.statistics, 2, 1)
        Atomics.store(message.statistics, 7, new Date().getTime())
        parentPort.postMessage({threadId: tempId, status: 0});

    }
});

5、run.js和text.js中的一些参数,可以挪到config.js里,方便维护

CentOS 6.4 手动部署 Discourse 全流程:PostgreSQL Redis Nginx Unicorn Discourse 是一款基于 Ruby on Rails 构建的现代化开源社区论坛系统,其运行依赖 PostgreSQL 强一致性事务、Redis 高性能缓存与消息队列、Nginx 反向代理及 Unicorn 应用服务器等核心组件。理解各组件版本兼容性、进程通信机制与系统级调优(如文件描述符、inotify 限制、内存分配策略)是保障高可用社区服务的基础。在老旧但广泛存在的 CentOS 6.4 环境中,因内核、glibc 和 OpenSSL 版本限制,无法使用 Docker 官方方案,必须通过源码编译方 阅读详情

相关推荐

Ubuntu 18.04 部署 pgAdmin 4 Server Mode 完整指南

pgAdmin 是 PostgreSQL 最主流的开源 Web 管理工具,其 Server Mode 支持多用户、权限控制、HTTPS 反向代理与审计日志,是生产环境的必备形态。该模式依赖 Python WSGI 服务架构,需在指定运行时路径下完成初始化配置、密钥生成与进程托管。在 Ubuntu 18.04 这类长期支持但已进入 ESM 阶段的系统中,必须严格匹配 Python 3.6 兼容性,并通过 systemd 实现可靠进程管理,配合 nginx 实现安全反向代理。本文聚焦 server mode 的

weixin_34258838的博客 467

WEB-WORKER进阶学习

WEB-WORKER 实用场景 密集型计算任务 (递归、计算、数据处理) 预处理请求 高频请求(心跳检测、用户行为捕捉等) 内部实现队列机制 初衷 一般做用户行为分析都会埋入锚点,当用户点击后通过AJAX向后台发送用户的操作、时间、功能等信息 在WEB-WORKER之前通过主线程发送...

chenhui88889的博客 323

基于Playwright与Asyncio的高效动态网页数据采集实战

在数据采集领域,动态网页内容渲染和反爬机制是常见的技术挑战。其核心原理在于网站通过JavaScript异步加载关键数据,传统静态爬虫难以直接获取。为应对此挑战,现代爬虫技术栈引入了浏览器自动化与异步编程模型。Playwright作为新一代浏览器自动化库,能够模拟真实用户操作,无缝处理JavaScript渲染,并提供稳定的浏览器上下文管理以对抗检测。结合Python的Asyncio异步I/O框架,可以实现非阻塞的并发请求,将等待网络响应的时间充分利用,从而大幅提升采集效率。这种技术组合在需要实时获取高动态、强

weixin_30216561的博客 393

nodejs连接postgre_nodejs连接postgres

安装驱动建议使用pg-pool,但要同时安装pg与pg-poolcnpm install pg pg-pool --save编写模块/**postgres.js*/const Pool = require(‘pg-pool‘);const config = {user: ‘postgres_user‘,password: ‘postgres_password‘,host: ‘postgres_ip...

weixin_39555320的博客 483

基于pytest的企业级多租户自动化测试实践

多租户架构作为SaaS服务的核心技术方案,通过数据隔离与资源共享实现高效服务交付。其测试验证需要特殊设计,重点解决租户隔离、并发控制等核心问题。pytest测试框架凭借灵活的fixture机制和丰富插件生态,成为构建多租户测试体系的理想选择。通过设计租户感知的测试夹具、组织跨租户隔离验证用例,结合PostgreSQL行级安全(RLS)等数据库特性,可有效验证数据隔离策略。在金融科技等高性能场景中,采用pytest-xdist实现分布式测试,配合线程模拟和重试机制,能可靠验证支付系统等关键业务的并发处理能力。

weixin_30256901的博客 353

LangGraph对话系统配置与性能优化实战

对话系统中的会话隔离与状态管理是核心技术难点,通过唯一标识符实现多线程会话隔离是常见解决方案。LangGraph框架通过thread_id和user_id参数实现会话隔离与数据持久化,其中thread_id作为检查点的命名空间标识,user_id支持多租户场景。在工程实践中,合理配置检查点器(如InMemorySaver和PostgresSaver)可显著提升系统性能,例如通过连接池优化和索引策略降低数据库负载。本文深入解析了LangGraph的运行时配置机制,并分享了电商客服系统中将吞吐量提升7倍的实战经

weixin_34387468的博客 393

NodeJs 多线程(worker_threads)

Javascript的运行,我们知道是单线程的,目的是为了解决内存冲突等的问题,同时单线程的设计也方便问题的查找和解决,在浏览器端,单线程基本都可以满足,但是在NodeJS服务端的话,如果有大规模的计算或者耗时业务流程就会堵塞后面的请求,比如有一个客户端请求,需要从数据库里面取出数据,然后进行各种计算,一般计算过程都是用JS写的,如果这个计算过程很耗时(假如需要10s),就会导致后面的请求得不到响应,之前我们的做法就是N-API写一个C++的addon去开辟新线程去计算或者直接用模块child-proces

SpringDou的博客 4918

从零构建高精度电子秤:HX711与STM32的时序通信陷阱与实战避坑指南

本文详细解析了使用STM32F103C8T6与HX711模块构建高精度电子秤的通信时序陷阱与实战解决方案。重点探讨了微秒级延迟实现、数据读取算法、校准方法和滤波优化,帮助开发者避开常见通信问题,提升电子秤的测量精度和稳定性。

data3的博客 781

PostgreSQL sharding : citus 系列5 - worker节点网络优化

背景 citus 节点间的网络需求: 1、cn节点访问所有worker节点。oltp业务的访问较频繁。 2、重分布数据时,worker节点间相互访问。访问频度不大,OLAP业务常见,一旦有可能数...

congnaoluan7899的博客 804

告别抓包失败!保姆级配置:让Burp+Proxifier稳定抓取任意微信小程序

本文提供了一套完整的Burp+Proxifier配置方案,确保稳定抓取微信小程序数据。从环境准备、工具选型到Burp Suite深度配置和Proxifier精准设置,详细解决了证书安装、进程捕获和乱码解析等核心问题,帮助开发者告别抓包失败,提升调试效率。

weixin_28738165的博客 451

基于 LSTM 的船舶轨迹预测,单步预测

基于 LSTM 的船舶轨迹预测,单步预测

fyuhao的博客 1万+

yii2 时间区间查询三

再一次的用到了时间区间查询,跟上次仍然不一样。 这次是在_search的activeForm 中使用 首先 composer下载安装小部件 composer require "kartik-v/yii2-date-range": "*" 这里安装时如果提示“:”有问题,可以直接composer require "kartik-v/yii2-date-range" 引入:use kartik\daterange\DateRangePicker; form里面使用 <?= $form->f

weixin_41987365的博客 1041

基于Simulink的双向DC-DC变换器在储能系统中的应用仿真

摘要:本文详细介绍了基于Simulink的双向DC-DC变换器在光伏储能系统中的仿真实现。主要内容包括:1)采用非隔离型双向Buck-Boost拓扑作为储能系统枢纽;2)针对750V直流微网中的20kWh锂电池接口场景进行建模;3)详细阐述双闭环控制器设计(电压外环+电流内环)、工作模式判断逻辑等关键步骤;4)通过仿真验证了系统在功率阶跃和模式切换下的性能。文章提供了完整的建模流程和控制方法,为储能系统接口设计提供了实用参考。

amy_mhd的博客 177

LangGraph从开发到生产部署:踩了4个坑才知道“本地跑通了“和“上线能用了“差多远

LangGraph 是LangChain 生态中专门用于构建、编排与执行多步骤、多代理(Multi-Agent)复杂 AI 工作流的可视化 / 代码化开发平台,核心解决传统 LLM 应用 “单轮对话、线性执行、无状态管理” 的局限性,支持构建具备循环、分支、状态持久化、多代理协作的高级 AI 系统(如自主 Agent、工作流引擎、复杂 RAG 增强系统)。它是 LangChain 官方推出的 “工作流编排层”,既提供Python 代码 SDK(核心开发方式),也配套。

专注 Java / Python 开发,AI 大模型应用学习,持续输出源码教程,实战项目案例,学习笔记,拒绝空话,只写能直接跑的代码与可落地方案,关注我,一起少走弯路。 1408

STM32cubeMX配置FreeRTOS软件定时器

文章目录前言1.软件定时器概述一.软件定时器特性二、使用cubeMX生成软件定时器总结 前言 本文主要带大家了解什么是软件定时器,并且带大家使用cubeMX配置软件定时器。 1.软件定时器概述 一.软件定时器特性 软件定时器就是一个闹钟当时间到了就执行相对应的任务或者代码。软件定时器是基于系统滴答中断的。在FreeRTOS中我们可以设置无数个软件定时器。 指定时间:启动定时器和运行回调函数,两者的间隔被称为定时器的周期 (period)。 指定类型定时器有两种类型: 1.一次性 这类定时器启动后,它的回调函

m0_49476241的博客 6948

YOLO小目标检测优化:9种实用方案,准确率直接提升15%

小目标检测是个系统工程,没有银弹,但有明确的优化路径。优先搞数据。Copy-Paste + 提升分辨率,这俩加起来成本最低、收益最大,能解决80%的小目标问题。别一上来就改模型结构。调参走在改结构前面。锚框聚类、损失加权、增强优化,这些都是零成本的,先做满了再说改模型的事。P2层是大杀器,但不要轻易用。加了P2层,TensorRT部署、后处理、速度都要跟着调,工程化工作量翻倍。数据和训练做到位还不够,再加也不迟。滑动窗口是兜底的。能从训练端解决的问题,就不要拖到推理端。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 186

pgrust 性能调优 10 大技巧:榨干 Rust 数据库的每一分性能

pgrust 性能调优是每个数据库爱好者和开发者都不该错过的话题。作为一个用 Rust 重写 PostgreSQL 的开源数据库项目,pgrust 在保持与 Postgres 18.3 磁盘兼容、通过超过 46,000 条回归查询的同时,带来了惊人的性能潜力:新版本的事务负载比原生 Postgres 快 50%,分析型负载更是快约 300 倍。本文为你整理 10 个简单实用的 pgrust 性能调

gitblog_00754的博客 990

把 ABAP SQL 窗口函数讲透:从 OVER 到 LEAD、RANK 与累计分析

ABAP SQL窗口函数在不丢失明细记录的前提下,为每行数据提供组内统计和排名功能。它通过OVER子句定义计算窗口,支持三类函数:聚合型(AVG/SUM等)、排名型(ROW_NUMBER/RANK等)和取值型(LEAD/LAG)。相比GROUP BY会合并多行数据,窗口函数保留原始记录同时附加计算结果,特别适合需要保留明细又要展示统计信息的业务场景,如销售排名、客户分层分析等。语法核心是OVER子句,通过PARTITION BY分组,ORDER BY排序,可灵活定义计算范围。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1272

Buzz性能优化技巧:提升relay服务器响应速度的7个方法

Buzz作为一款高效的分布式通信平台,其relay服务器的响应速度直接影响用户体验。本文将分享7个实用技巧,帮助你通过优化数据库连接、调整线程池配置、实现智能缓存等方式,显著提升Buzz relay服务器的处理能力和响应效率。 ## 1. 优化数据库连接池配置 数据库连接是relay服务器性能的关键瓶颈之一。Buzz采用PostgreSQL作为主数据库,通过合理配置连接池参数可以有效减少连接建

gitblog_00479的博客 995

使用verilog实现基于FPGA的TDC设计

verilog实现TDC 高精度时间数字转换器概述(TDC) 简介: TDC被用于测量时间间隔,应用在物理研究、飞行时间测量领域等。 本设计使用verilog实现并在xilinx和altera的FPGA上均可实现! 设计中使用到下述几个模块,包括FIFO,COUNT等,在xilinx下也使用到了一些原语等。下面有实现的代码和仿真截图等。 顶层模块设计如下: module top( input wire start, input wire stop, input wire clk, output wire T

QQ_778132974的博客 6253

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

技术深度解析:Judge0分布式代码执行系统架构与安全沙箱设计

Judge0是一个基于Rails框架构建的分布式在线代码执行系统,采用微服务架构和安全沙箱技术,为在线编程教育、技术评估和AI代码验证场景提供企业级解决方案。系统支持90+编程语言的安全执行,通过容器化部署和异步任务队列实现高并发处理,日均处理能力可达百万级代码提交。 ## 技术挑战与行业痛点分析 在线代码执行系统面临的核心技术挑战集中在安全隔离、资源控制和性能扩展三个维度。传统解决方案如直接

gitblog_01123的博客 1023

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

在国产麒麟V10SP2服务器上,我是如何一步步搞定PostgreSQL 12和PostGIS 3.1.4离线部署的(附完整依赖包清单)

本文详细记录了在国产麒麟V10SP2服务器上离线部署PostgreSQL 12和PostGIS 3.1.4的全过程,包括依赖包收集、源码编译技巧、常见报错解决方案及性能优化建议。特别针对银河麒麟服务器操作系统的特性,提供了完整的离线安装指南和依赖包清单,帮助开发者在隔离网络环境下高效搭建GIS数据库环境。

dingqiongliang0363的博客 382

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

PostgreSQL 12.4 源码编译安装:CentOS 7 系统 10 个关键配置参数详解

本文详细介绍了在CentOS 7系统上源码编译安装PostgreSQL 12.4的完整流程,重点解析了10个关键配置参数对系统性能和安全性影响。包括环境准备、源码获取、核心参数详解(如--with-openssl加密支持、--with-python扩展等)、编译优化建议及安全加固措施,帮助用户高效部署高性能PostgreSQL数据库。

weixin_34288121的博客 483

Bilibili-Evolved 小窗播放器大小定制:mini-player-size 组件的缩放原理与拖拽实现

本文围绕 Bilibili-Evolved(哔哩哔哩增强脚本)中的「小窗播放器大小」(mini-player-size)组件展开。该组件允许用户自定义 B 站小窗(迷你)播放器的尺寸,并支持鼠标拖拽四角实时调整、可选锁定 16:9 宽高比。读完本文,你将理解它如何通过 CSS 变量驱动播放器缩放、如何注入四个方向的拖拽手柄并计算尺寸钳制,以及它与 B 站 bpx 播放器 `playerModeCh

gitblog_01000的博客 801

工作日志记录

记录工作中细碎的感悟和经验,持续补充中。

WSTONECH的博客 496

LangGraph状态持久化实战:从检查点存储到生产级高可用

在大模型应用开发中,状态管理是保障对话连续性与业务一致性的核心能力。LangGraph通过检查点(Checkpoint)机制实现有向无环图执行过程的可恢复性,其本质并非简单序列化State对象,而是持久化节点状态、执行路径与调度元数据构成的决策快照。该机制支撑了电商客服、金融投顾等场景下的断点续聊、异步回调续签与多实例协同等关键能力。技术选型需兼顾一致性(PostgreSQL)、低延迟(Redis热缓存)与唯一性(UUIDv4检查点ID),并规避序列化陷阱、缓存击穿与连接池瓶颈。本文聚焦LangGraph持

weixin_30859423的博客 366
上一篇: 5.7 call bind apply的使用
下一篇: 5.8 ?. ?? ??=用法
LetsStudy
博客等级 码龄9年 96粉丝 323原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值