尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Prowler Jira 集成连接测试的并发优化:`test_connection()` 并行拉取项目 Issue Types 的原理与实践

Prowler Jira 集成连接测试的并发优化:`test_connection()` 并行拉取项目 Issue Types 的原理与实践 Prowler Jira 集成连接测试的并发优化test_connection()并行拉取项目 Issue Types 的原理与实践【免费下载链接】prowlerProwler is the world’s most widely used open-source cloud security platform that automates security and compliance across any cloud environment.项目地址: https://gitcode.com/GitHub_Trending/pr/prowler导读本文围绕 Prowler 发布说明片段jira-connection-test-parallel-issue-types.fixed展开深入剖析 Prowler 的 Jira 集成中Jira.test_connection()的并发改造为什么原来逐个请求项目 Issue Types 会让多项目账户的连接验证耗时呈线性膨胀改造后又如何通过ThreadPoolExecutor将耗时从数十秒且随项目数无界增长压缩到近乎恒定。读完本文你将理解 Prowler Jira 集成连接测试的完整调用链、并行化实现细节、容错设计以及对应的测试验证方式可直接对照源码继续深入。变更概述从串行到并行的连接测试发布说明原文如下Jira.test_connection()now fetches each projects issue types concurrently instead of one request at a time, so accounts with many Jira projects no longer take tens of seconds (unbounded, scaling with the project count) to verify the connection.这段变更描述了三件事行为变化Jira.test_connection()现在并发获取每个项目的 Issue Types而不是一次一个请求。问题背景改造前账户下 Jira 项目越多连接验证耗时越长呈无界线性增长多项目账户需要数十秒才能完成验证。改造收益连接验证耗时不再随项目数量线性放大。实现位于 prowler/lib/outputs/jira/jira.py对应的变更说明文件为 prowler/changelog.d/jira-connection-test-parallel-issue-types.fixed.md。Jira 集成在 Prowler 中的定位Prowler 的 Jira 集成是输出通道Outputs体系的一部分位于 prowler/lib/outputs/jira/核心由三个文件组成jira.pyJira主类封装认证、项目与 Issue Types 查询、Issue 创建等全部 Jira API 交互models.pyJiraConnection、JiraCreationResult、JiraIssueReference等数据模型exceptions/exceptions.py完整的异常体系覆盖认证、项目、Issue Types、建单、连接测试等各环节。Jira类的类注释明确说明该集成目前限定单个 Jira Cloud所有 Issue 都会创建到同一个 Cloud ID 下。类中定义的关键常量也值得注意jira.pyREQUEST_TIMEOUT 90所有 Jira API 请求的超时上限默认 90 秒ISSUE_STATUS_BATCH_SIZE 100批量查询 Issue 状态时的分批大小LABEL_MAX_LENGTH 255Jira 标签长度上限用于标签清洗OAuth 相关端点AUTH_URL、TOKEN_URL、API_TOKEN_URL分别对应授权、换 Token、查询可访问资源三个流程。连接测试做了什么test_connection()的完整流程Jira.test_connection()是静态方法jira.py签名如下staticmethod def test_connection( redirect_uri: str None, client_id: str None, client_secret: str None, user_mail: str None, api_token: str None, domain: str None, raise_on_exception: bool True, ) - JiraConnection:一次完整的连接测试分三步第一步初始化并完成认证根据传入参数自动选择两种认证方式jira.py认证方式所需参数流程OAuth 授权码流redirect_uriclient_idclient_secret生成授权 URL → 等待用户输入授权码 →get_auth()换取 access/refresh tokenBasic Authuser_mailapi_tokendomainget_basic_auth()将邮箱与 API Token 做 Base64 编码并从https://{domain}.atlassian.net/_edge/tenant_info解析 Cloud ID参数不满足任一组合时抛出JiraInvalidParameterError。认证成功后两种方式都会拿到_access_token与_cloud_id这是后续所有 API 调用的凭证基础。第二步拉取项目列表get_projects()jira.py调用 Jira REST APIGET https://api.atlassian.com/ex/jira/{cloud_id}/rest/api/3/project返回{PROJECT_KEY: 项目名}形式的字典。若响应为空账户下没有可访问项目抛出JiraNoProjectsError非 200 响应则抛出带http_status与retry_after的JiraGetProjectsResponseError。第三步为每个项目拉取可用 Issue Types本次优化的核心get_available_issue_types(project_key)jira.py对单个项目调用GET https://api.atlassian.com/ex/jira/{cloud_id}/rest/api/3/issue/createmeta?projectKeys{project_key}expandprojects.issuetypes.fields并提取projects[0].issuetypes中的name列表如[Bug, Task, Story]。这个方法本身一次只处理一个项目——改造前的test_connection()正是在这一层用 for 循环逐个串行调用于是耗时 单请求延迟 × 项目数随项目数线性放大多项目账户因此要等数十秒。并发改造的源码实现本次变更的核心代码在 jira.pyprojects jira.get_projects() issue_types {} with ThreadPoolExecutor(max_workers10) as executor: future_to_project { executor.submit(jira.get_available_issue_types, project_key): project_key for project_key in projects } for future in as_completed(future_to_project): project_key future_to_project[future] try: issue_types[project_key] future.result() except Exception as e: logger.warning( fFailed to get issue types for project {project_key}: {e} )实现要点线程池固定 10 个 workerThreadPoolExecutor(max_workers10)限制并发度避免对 Jira API 造成突发压力同时把 10 个并发请求的延迟重叠在一起。整体耗时理论上从项目数 × 单请求延迟降为约 项目数/10 × 单请求延迟受网络与 Jira 端并发能力制约。提交-收集模式用字典推导式为每个项目提交一个任务future_to_project记录 future 与项目键的映射as_completed()按完成顺序收集结果先完成先写入不依赖提交顺序。逐项目容错单个项目拉取失败例如集成用户对该项目没有 create issue 权限只记录logger.warning不影响其他项目的结果也不会让整个连接测试失败。这正是 get_available_issue_types 中把createmeta 返回空 projects视为预期条件而非致命错误的原因。成功返回最终返回JiraConnection(is_connectedTrue, projectsprojects, issue_typesissue_types)其中issue_types是{project_key: [issue_type_name, ...]}的字典与JiraConnection数据模型models.py 中的issue_types: dict字段对应。异常处理与降级语义test_connection()的异常处理体现了清晰的降级策略jira.py捕获JiraNoProjectsError、JiraGetCloudIDResponseError、JiraGetCloudIDError、JiraAuthenticationError、JiraBasicAuthError、JiraGetProjectsResponseError等具体异常当raise_on_exceptionTrue默认时直接向上抛出让调用方感知失败原因当raise_on_exceptionFalse时返回携带error字段的JiraConnection对象is_connected视情况为False供需要软失败如 UI 后台校验的场景使用未预期的兜底异常统一包装为JiraTestConnectionError。值得注意的是串行时代若某个项目的 createmeta 请求超时会拖慢甚至卡住整个测试并发改造后单个 future 的异常被as_completed循环内的try/except消化为警告测试的健壮性同步提升。测试如何验证并发这件事并行改造不是靠嘴上说测试文件 tests/lib/outputs/jira/jira_test.py 中有专门用例test_test_connection_fetches_issue_types_concurrentlyjira_test.py巧妙之处在于使用了threading.Barrier# Every call blocks until all 5 arrive; a sequential fetch would time out # at the barrier and surface as a per-project failure instead of a result. barrier Barrier(5, timeout5) def fake_issue_types(project_key): barrier.wait() return [project_key]5 个项目、5 个线程各调用一次fake_issue_types每个调用都会在barrier.wait()上等待其他 4 个调用全部到达。如果实现是串行的第一个调用就会在 Barrier 上阻塞 5 秒后超时测试将看到逐项目失败而非完整结果只有真正并发执行5 个调用才能同时越过 Barrier 并返回完整映射。因此该用例通过即证明并发确实发生。同类测试还覆盖了多种场景test_test_connection_successful与test_test_connection_successful_basic_authjira_test.py分别验证 OAuth 与 Basic Auth 下成功返回projects与issue_typestest_test_connection_partial_issue_types_failurejira_test.py某项目拉取失败时连接仍为is_connectedTrue失败项目只产生 WARNING 日志且不产生 ERROR 日志test_test_connection_failed/test_test_connection_failed_basic_auth认证失败正确抛出对应异常test_test_connection_empty_issue_types_logs_one_warning全部项目都无 Issue Types 时只记录一条警告test_get_projects_sends_timeoutjira_test.py验证get_projects()确实传递了Jira.REQUEST_TIMEOUT超时参数。与旧实现get_metadata()的对比值得注意的是Jira类中仍保留着串行遍历的get_metadata()方法jira.py它逐个项目串行请求 createmeta 并组装{KEY: {name: ..., issue_types: [...]}}。对照get_metadata()与test_connection()的差异可以直观看到get_metadata()返回的是带项目名与 Issue Types 的完整元数据供需要全部细节的场景使用test_connection()只关心能不能连上、有哪些项目、各项目支持哪些 Issue Types因此可以只保留 key → issue_types 的映射并用线程池做并行化。这也说明并发优化是test_connection()这个特定路径的定向改进其取舍并发换取低延迟、逐项目容错换取高可用值得在集成其他 API 时参考。小结与进一步阅读本次变更解决的是 Prowler Jira 集成中一个典型的多项目账户连接验证慢问题将Jira.test_connection()中逐项目拉取 Issue Types 的串行请求改为ThreadPoolExecutor(max_workers10)并发执行配合逐项目容错使验证耗时不再随项目数线性放大。核心实现、数据模型与异常定义均可直接查阅实现prowler/lib/outputs/jira/jira.pytest_connection位于 L1099-L1212并发逻辑位于 L1141-L1162数据模型prowler/lib/outputs/jira/models.py异常体系prowler/lib/outputs/jira/exceptions/exceptions.py测试用例tests/lib/outputs/jira/jira_test.py其中并发验证用例见 L830-L855如果你在自建集成中遇到验证连接时 API 调用数随资源数线性增长的同类问题本文的线程池 固定 worker 逐项容错 Barrier 并发测试这一整套模式可以直接复用到你的场景中。【免费下载链接】prowlerProwler is the world’s most widely used open-source cloud security platform that automates security and compliance across any cloud environment.项目地址: https://gitcode.com/GitHub_Trending/pr/prowler创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表