当前位置: 首页 > article >正文

.Net HttpClient 使用准则

HttpClient 使用准则

System.Net.Http.HttpClient 类用于发送 HTTP 请求以及从 URI 所标识的资源接收 HTTP 响应。 HttpClient 实例是应用于该实例执行的所有请求的设置集合,每个实例使用自身的连接池,该池将其请求与其他请求隔离开来。

从 .NET Core 2.1 开始,SocketsHttpHandler 类提供实现,使行为在所有平台上保持一致。

准备工作:先执行下面单元,以启动WebApi及设置全局对象、方法及其它

//初始化:必须先执行一次
#!import ./ini.ipynb

统一使用示例

{ //大括号: 1、作用域隔离 2、方便整体代码折叠Console.WriteLine(global_api_config.BaseUrl);
}

启动WebApi

#启动已发布的WebApi项目
# 使用dotnet命令启动的程序,进程名均为 dotnet,不好关闭
# Start-Process -FilePath dotnet -ArgumentList ".\Publish\HttpClientStudy.WebApp\HttpClientStudy.WebApp.dll"# 此种,进程名固定
Start-Process -FilePath ".\Publish\HttpClientStudy.WebApp\HttpClientStudy.WebApp.exe"

关闭WebApi

# 关闭项目进程
$WebAppProcName ="HttpClientStudy.WebApp";
$WebAppProc = Get-Process $WebAppProcName -ErrorAction Ignore
if($null -eq $WebAppProc)
{Write-Host "进程没有找到,可能已经关闭"
}
else {$WebAppProc.Kill();Write-Host "$WebAppProcName 进程已退出"
}

1、DNS 行为

HttpClient 仅在创建连接时解析 DNS。它不跟踪 DNS 服务器指定的任何生存时间 (TTL)。

如果 DNS 条目定期更改(这可能在某些方案中发生),客户端将不会遵循这些更新。 要解决此问题,可以通过设置 PooledConnectionLifetime 属性来限制连接的生存期,以便在替换连接时重复执行 DNS 查找。

using System.Net.Http;
{var handler = new SocketsHttpHandler{// 15分钟PooledConnectionLifetime = TimeSpan.FromMinutes(15) };var sharedClient = new HttpClient(handler);sharedClient.Display();
}

上述 HttpClient 配置为重复使用连接 15 分钟。 PooledConnectionLifetime 指定的时间范围过后,系统会关闭连接,然后创建一个新连接。

2、共用连接(底层自动管理连接池)

HttpClient 的连接池链接到其基础 SocketsHttpHandler。
释放 HttpClient 实例时,它会释放池中的所有现有连接。 如果稍后向同一服务器发送请求,则必须重新创建一个新连接。
因此,创建不必要的连接会导致性能损失。
此外,TCP 端口不会在连接关闭后立即释放。 (有关这一点的详细信息,请参阅 RFC 9293 中的 TCP TIME-WAIT。)如果请求速率较高,则可用端口的操作系统限制可能会耗尽。

为了避免端口耗尽问题,建议将 HttpClient 实例重用于尽可能多的 HTTP 请求。

什么是连接池

SocketsHttpHandler为每个唯一端点建立连接池,您的应用程序通过HttpClient向该唯一端点发出出站HTTP请求。在对端点的第一个请求上,当不存在现有连接时,将建立一个新的HTTP连接并将其用于该请求。该请求完成后,连接将保持打开状态并返回到池中。

对同一端点的后续请求将尝试从池中找到可用的连接。如果没有可用的连接,并且尚未达到该端点的连接限制,则将建立新的连接。达到连接限制后,请求将保留在队列中,直到连接可以自由发送它们为止。

如何控制连接池

有三个主要设置可用于控制连接池的行为。

  • PooledConnectionLifetime,定义连接在池中保持活动状态的时间。此生存期到期后,将不再为将来的请求而合并或发出连接。

  • PooledConnectionIdleTimeout,定义闲置连接在未使用时在池中保留的时间。一旦此生存期到期,空闲连接将被清除并从池中删除。

  • MaxConnectionsPerServer,定义每个端点将建立的最大出站连接数。每个端点的连接分别池化。例如,如果最大连接数为2,则您的应用程序将请求发送到两个www.github.com和www.google.com,总共可能最多有4个打开的连接。

默认情况下,从.NET Core 2.1开始,更高级别的HttpClientHandler将SocketsHttpHandler用作内部处理程序。没有任何自定义配置,将应用连接池的默认设置。

PooledConnectionLifetime默认是无限的,因此,虽然经常使用的请求,连接可能会无限期地保持打开状态。该PooledConnectionIdleTimeout默认为2分钟,如果在连接池中长时间未使用将被清理。MaxConnectionsPerServer默认为int.MaxValue,因此连接基本上不受限制。

如果希望控制这些值中的任何一个,则可以手动创建SocketsHttpHandler实例,并根据需要进行配置。

//手动配置 SocketsHttpHandler
{var socketsHandler = new SocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromMinutes(10),PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),MaxConnectionsPerServer = 10};var client = new HttpClient(socketsHandler);client.Display();
}

在前面的示例中,对SocketsHttpHandler进行了配置,以使连接将最多在10分钟后停止重新发出并关闭。如果闲置5分钟,则连接将在池的清理过程中被更早地删除。我们还将最大连接数(每个端点)限制为十个。如果我们需要并行发出更多出站请求,则某些请求可能会排队等待,直到10个池中的连接可用为止。
要应用处理程序,它将被传递到HttpClient的构造函数中。

测试连接寿命

//测试连接寿命
{Console.WriteLine("程序运行大约要10-20秒,请在程序退出后,执行下面命令行查看网络情况");//自定义行为var socketsHandler = new SocketsHttpHandler{//连接池生命周期为10分钟:连接在池中保持活动时间为10分钟PooledConnectionLifetime = TimeSpan.FromMinutes(10),//池化链接的空闲超时时间为5分钟: 5分钟内连接不被重用,则被释放后销毁PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),//每端点的最大连接数设置为10个MaxConnectionsPerServer = 10};var client = new HttpClient(socketsHandler){BaseAddress = new Uri(global_api_config.BaseUrl)};var displayer = "".Display();for (var i = 0; i < 5; i++){if(i>0){await Task.Delay(TimeSpan.FromSeconds(2));}_ = await client.GetAsync(global_default_page);displayer.Update(($"第{i+1}次请求完成"));await Task.Delay(TimeSpan.FromSeconds(2));}
}

使用自定义设置,依次向同一端点发出5个请求。在每个请求之间,暂停两秒钟。输出从DNS检索到的网站服务器的IPv4地址。我们可以使用此IP地址来查看通过PowerShell中发出的netstat命令对其打开的连接:

# 若查询不到,则异常
#!set --value @csharp:global_netstat_filter --name queryFilterWrite-Host "请先执行上面的单元,再执行本单元"
Write-Host "网络状态"
netstat -ano | findstr $queryFilter

在这种情况下,到远程端点的连接只有1个。在每个请求之后,该连接将返回到池中,因此在发出下一个请求时可以重新使用。
如果更改连接的生存期,以使它们在1秒后过期,测试这对行为的影响:

//程序池设置
{  //自定义行为Console.WriteLine("程序运行大约要10-20,请在程序退出后,执行下面命令行查看网络情况");var socketsHandler2 = new SocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromSeconds(1),PooledConnectionIdleTimeout = TimeSpan.FromSeconds(1),MaxConnectionsPerServer = 1};var client2 = new HttpClient(socketsHandler2){BaseAddress = new Uri(global_api_config.BaseUrl)};var displayer = "".Display();for (var i = 0; i < 5; i++){if(i>0){await Task.Delay(TimeSpan.FromSeconds(2));}_ = await client2.GetAsync(global_default_page);displayer.Update(($"第{i+1}次请求完成"));await Task.Delay(TimeSpan.FromSeconds(2));}//调用命令行,显示查看网络情况string command = $"netstat -ano | findstr {global_netstat_filter}";// 创建一个新的ProcessStartInfo对象ProcessStartInfo startInfo = new ProcessStartInfo("cmd", $"/c {command}"){RedirectStandardOutput = true, // 重定向标准输出UseShellExecute = false, // 不使用系统外壳程序启动CreateNoWindow = true // 不创建新窗口};// 启动进程using (Process process = Process.Start(startInfo)){// 读取cmd的输出using (StreamReader reader = process.StandardOutput){string stdoutLine = reader.ReadToEnd();Console.WriteLine(stdoutLine);}}
}
#!set --value @csharp:global_netstat_filter --name queryFilter
netstat -ano | findstr $queryFilter

在这种情况下,我们可以看到使用了五个连接。其中的前四个在1秒后从池中删除,因此无法在下一个请求中重复使用。结果,每个请求都打开了一个新连接。现在,原始连接处于TIME_WAIT状态,并且操作系统无法将其重新用于新的出站连接。最终连接显示为ESTABLISHED,因为我在它过期之前就抓住了它。

测试最大连接数

/*功能:将MaxConnectionsPerServer限制为2。然后启动200个任务,每个任务都向同一端点发出HTTP请求。这些任务将同时运行。所有请求竞争所花费的时间将写入控制台。随即调用用netstat命令查看连接:则根据定义的限制,我们可以看到两个已建立的连接。
*/
{Console.WriteLine("开始请求网络...");var socketsHandler = new SocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromSeconds(60),PooledConnectionIdleTimeout = TimeSpan.FromMinutes(20),MaxConnectionsPerServer = 2};var client = new HttpClient(socketsHandler){BaseAddress = new Uri(global_api_config.BaseUrl)};var sw = Stopwatch.StartNew();var tasks = Enumerable.Range(0, 200).Select(i => client.GetAsync(global_default_page));await Task.WhenAll(tasks);sw.Stop();Console.WriteLine($"共请求了200次,耗时 {sw.ElapsedMilliseconds} 毫秒");//执行查看网络状态方法Console.WriteLine("当前网络状态");var message = HttpClientStudy.Core.Utilities.AppUtility.RunCmd($"netstat -ano | findstr {global_netstat_filter}");Console.WriteLine(message);
}
# 重新查询当前网络状态
#!set --value @csharp:global_netstat_filter --name queryFilter
netstat -ano | findstr $queryFilter

如果我们调整此代码以允许MaxConnectionsPerServer = 10,则可以重新运行该应用程序。耗时将减少大约4倍。

{   //MaxConnectionsPerServer 设置为10:网络连接将增加到10个,耗时将减少到1/4Console.WriteLine("开始请求网络...");var socketsHandler = new SocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromSeconds(60),PooledConnectionIdleTimeout = TimeSpan.FromMinutes(20),MaxConnectionsPerServer = 10};var client = new HttpClient(socketsHandler){BaseAddress = new Uri(global_api_config.BaseUrl)};//client.Display();var sw = Stopwatch.StartNew();var tasks = Enumerable.Range(0, 200).Select(i => client.GetAsync(global_default_page));await Task.WhenAll(tasks);sw.Stop();Console.WriteLine($"共请求了200次,耗时 {sw.ElapsedMilliseconds} 毫秒");//执行查看网络状态方法Console.WriteLine("当前网络状态");var message = AppUtility.RunCmd($"netstat -ano | findstr {global_netstat_filter}");Console.WriteLine(message);
}

3、推荐使用方式

总则:

一、 应使用长期客户端(静态对象、单例等),并设置 PooledConnectionLifetime。这能解决DNS问题和套接字耗尽问题。

二、 使用 IHttpClientFactory 创建的短期客户端:

  • 在 .NET Core 和 .NET 5+ 中:

    • 根据预期的 DNS 更改,使用 static 或 singletonHttpClient 实例,并将 PooledConnectionLifetime 设置为所需间隔(例如 2 分钟)。 这可以解决端口耗尽和 DNS 更改两个问题,而且不会增加 IHttpClientFactory 的开销。 如果需要模拟处理程序,可以单独注册它。

    • 使用 IHttpClientFactory,可以针对不同的用例使用多个以不同方式配置的客户端。 但请注意,工厂创建的客户端生存期较短,一旦创建客户端,工厂就不再可以控制它。
      工厂合并 HttpMessageHandler 实例,如果其生存期尚未过期,则当工厂创建新的 HttpClient 实例时,可以从池中重用处理程序。 这种重用避免了任何套接字耗尽问题。
      如果需要 IHttpClientFactory 提供的可配置性,我们建议使用类型化客户端方法。

  • 在 .NET Framework 中,使用 IHttpClientFactory 管理 HttpClient 实例。 如果不使用工厂,而是改为自行为每个请求创建新的客户端实例,则可能耗尽可用的端口。

提示: 如果应用需要 Cookie,请考虑禁用自动 Cookie 处理或避免使用 IHttpClientFactory。 共用 HttpMessageHandler 实例会导致共享 CookieContainer 对象。 意外的 CookieContainer 对象共享通常会导致错误的代码。

{ //不推荐的示例int requestCount =0;//这会建立10个 HttpClient //尽管使用了Using,不过Using只保证应用进程释放实例;但是http请求是跨操作系统、跨网络的操作,调用Using的进程管不了操作系统,更管不了网络。//如果把循环次数加大到 65535 就会一定导致夏套接字耗尽(2000以很可能就会出现)。Parallel.For(0,10,async (a,b)=>{using (var client = new HttpClient()){_ = await client.GetAsync (global_api_config.BaseUrl + global_default_page);}   Interlocked.Add(ref requestCount, 1);});
}{ //使用长期客户端using (var client = new HttpClient()){client.BaseAddress = new Uri(global_api_config.BaseUrl);for(int i=0; i<10; i++){//n次调用,均使用同一个 HttpClient 实例_ = await client.GetAsync(global_default_page);}}// 所有调用完成,才释放 HttpClient 实例
}

4、静态客户端的复原能力

#r "nuget:Polly"
#r "nuget:Microsoft.Extensions.Http.Resilience"
using System;
using System.Net.Http;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Http.Resilience;
using Polly;{var retryPipeline = new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new HttpRetryStrategyOptions{BackoffType = DelayBackoffType.Exponential,MaxRetryAttempts = 3}).Build();var socketHandler = new SocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromMinutes(15)};#pragma warning disable EXTEXP0001var resilienceHandler = new ResilienceHandler(retryPipeline){InnerHandler = socketHandler,};#pragma warning restore EXTEXP0001var httpClient = new HttpClient(resilienceHandler);httpClient.BaseAddress = new Uri(global_api_config.BaseUrl);var response = await httpClient.GetAsync(global_default_page);var htmlText = await response.Content.ReadAsStringAsync();Console.WriteLine($"共有{htmlText.Length}个字符");
}

相关文章:

.Net HttpClient 使用准则

HttpClient 使用准则 System.Net.Http.HttpClient 类用于发送 HTTP 请求以及从 URI 所标识的资源接收 HTTP 响应。 HttpClient 实例是应用于该实例执行的所有请求的设置集合&#xff0c;每个实例使用自身的连接池&#xff0c;该池将其请求与其他请求隔离开来。 从 .NET Core …...

【Canda】常用命令+虚拟环境创建到选择

目录 一、conda常用命令 二、conda 环境 2.1 创建虚拟环境 2.2 conda环境切换 2.3 查看conda环境 2.4 删除某个conda环境 2.5 克隆环境 三、依赖包管理 3.1 安装命令 3.2 更新包 3.3 卸载包 3.4 查看环境中所有包 3.5 查看某个包的版本信息 3.6 搜索包 四、环境…...

Lighthouse Core Web Vitals 指标详解与优化指南

vLighthouse Core Web Vitals 指标详解与优化指南 一、Core Web Vitals 概述 Google 在 2020 年推出的 Core Web Vitals(核心网页指标)是衡量用户体验质量的关键指标集合,现已成为搜索引擎排名的重要因素。Lighthouse 作为 Google 官方的网页质量评估工具,提供了对这些指…...

Qt进阶开发:QTcpServer的详解

文章目录 一、QTcpServer 简介二、常用成员函数的使用三、信号函数的使用四、虚函数的使用五、连接多客户端-服务端示例一、QTcpServer 简介 QTcpServer 是 Qt 网络模块中的一个核心类,用于实现 基于 TCP 协议的服务端(Server),它负责监听端口、接收客户端连接请求,并通过…...

Leetcode 3544. Subtree Inversion Sum

Leetcode 3544. Subtree Inversion Sum 1. 解题思路2. 代码实现 题目链接&#xff1a;3544. Subtree Inversion Sum 1. 解题思路 这一题我的思路上就是一个动态规划的思路&#xff0c;因为原则上我们只需要遍历一下所有的状态即可&#xff0c;但是这样显然时间复杂度过高&am…...

物理:由基本粒子组成的个体能否提炼和重组?

个体差异源于基本粒子组合的复杂性与随机性,这一假设若成立,确实可能为生物医学带来革命性突破——但需要突破技术、理论与系统层级的多重壁垒。以下从科学逻辑与技术路径展开分析: 一、随机组合中的共性与稳定结构 1. 自然界的自组织规律 涌现性(Emergence):尽管粒子组…...

信息学奥赛一本通 1535:【例 1】数列操作

【题目链接】 ybt 1535&#xff1a;【例 1】数列操作 【题目考点】 1. 树状数组 【解题思路】 本题为树状数组模板题&#xff0c;维护区间和&#xff0c;进行单点修改&#xff0c;区间查询。 详细讲解见&#xff1a;洛谷 P3374 【模板】树状数组 1&#xff08;树状数组解法…...

【登录认证】JWT令牌

一、概述 JWT全称:**JSON Web Token **(https://jwt.io/)定义了一种简洁的、自包含的格式&#xff0c;用于通信双方以json数据格式安全的传输信息。组成: ①第一部分:Header(头)&#xff0c;记录令牌类型、签名算法等。例如: (“alg”:" HS256"," type":“…...

手撕算法(定制整理版2)

最长无重复子字符串 class Solution(object):def lengthOfLongestSubstring(self, s):""":type s: str:rtype: int"""if not s:return 0max_len 0tp []for a in s:while a in tp:del tp[0]tp.append(a)if len(tp) > max_len:max_len len(…...

python3:文件与异常

本来这篇教程是打算在base python数据类型之后出的&#xff0c;但是计划赶不上变化&#xff0c;反正最后都要融会贯通&#xff0c;今日有时间、今天遇到了类似的问题&#xff0c;就今天做这一模块的整理&#xff0c;顺序不是重点。 参考我的上一篇博客&#xff1a;https://blo…...

【兽医电子处方软件】佳易王宠物医院电子处方管理系统:宠物医院诊所用什么软件?一键导入配方模板软件程序实操教程 #操作简单 #宠物医院软件下载安装

一、概述 软件试用版资源文件下载方法&#xff1a; 【进入头像主页第一篇文章最后 卡片按钮 可点击了解详细资料 或左上角本博客主页 右侧按钮了解具体资料信息】 本实例以 佳易王宠物医院电子处方管理系统软件 为例说明&#xff0c;其他版本可参考本实例。试用版软…...

centos7.x下,使用宝塔进行主从复制的原理和实践

操作原理&#xff1a; 一、主库配置 1.修改 MySQL 配置文件 # 编辑主库配置文件&#xff08;路径根据实际系统可能不同&#xff09; vim /etc/my.cnf # 添加以下配置 [mysqld] server-id 1 # 唯一 ID&#xff0c;主库设置为 1 log-bin mysql-bin …...

langchain学习

无门槛免费申请OpenAI ChatGPT API搭建自己的ChatGPT聊天工具 https://nuowa.net/872 基本概念 LangChain 能解决大模型的两个痛点&#xff0c;包括模型接口复杂、输入长度受限离不开自己精心设计的模块。根据LangChain 的最新文档&#xff0c;目前在 LangChain 中一共有六大…...

从“听不懂”到“能对话”,声网AI让语音交互不再难用

人们谁懂啊&#xff01;做智能客服系统的真的被传统语音机器整怕了&#xff01;以前那些基于规则的 IVR 系统&#xff0c;“卡顿感” 拉满还总答非所问&#xff0c;用户说啥都像在对牛弹琴。不能打断、没有上下文、流程死板到离谱&#xff0c;动不动就来句 “请再说一遍”&…...

VSCode设置SSH免密登录

引言 2025年05月13日20:21:14 原来一直用的PyCharn来完成代码在远程服务器上的运行&#xff0c;但是PyCharm时不时同步代码会有问题。因此&#xff0c;尝试用VSCode来完成代码SSH远程运行。由于VSCode每次进行SSH连接的时候都要手动输入密码&#xff0c;为了解决这个问题在本…...

Windows Java gRPC 示例

gRPC是一个开源高性能远程过程调用(RPC)框架,因为这个框架最早是由Goolge开发的,这里的g 代表的也即是Google。 关于gRPC更多的概念介绍可以参考: gRPC 基本介绍 本篇快速介绍在Windows环境下使用 Java 语言如何实现 gRPC 的服务端和客户端调用。 1. 环境准备 JDK 21Ma…...

问题及解决02-处理后的图像在坐标轴外显示

一、问题 在使用matlab的appdesigner工具来设计界面&#xff0c;可以通过点击处理按钮来处理图像&#xff0c;并将处理后的图像显示在坐标轴上&#xff0c;但是图像超出了指定的坐标轴&#xff0c;即处理后的图像在坐标轴外显示。 问题图如下图所示。 原来的坐标轴如下图所…...

EasyX开发——绘制跟随鼠标移动的小球

游戏主循环&#xff1a; #include<graphics.h>int main() {initgraph(1280, 720);while (true){}return 0; } peekmessage函数&#xff1a;如果成功拉取到了消息&#xff0c;函数就会返回true&#xff0c;反之就会返回false 使用另外一个循环来不断地从消息队列当中拉取…...

【Qt开发】信号与槽

目录 1&#xff0c;信号与槽的介绍 2&#xff0c;信号与槽的运用 3&#xff0c;自定义信号 1&#xff0c;信号与槽的介绍 在Qt框架中&#xff0c;信号与槽机制是一种用于对象间通信的强大工具。它是在Qt中实现事件处理和回调函数的主要方法。 信号&#xff1a;窗口中&#x…...

APS排程系统(Advanced Planning and Scheduling,高级计划与排程系统)

APS排程系统&#xff08;Advanced Planning and Scheduling&#xff0c;高级计划与排程系统&#xff09;是一种基于供应链管理和约束理论的智能生产管理工具&#xff0c;旨在通过动态优化资源分配和生产流程&#xff0c;解决制造业中的复杂计划问题。以下是其核心要点解析&…...

使用聊天模型和提示模板构建一个简单的 LLM 应用程序

官方教程 官方案例 在上面的链接注册后&#xff0c;请确保设置您的环境变量以开始记录追踪 export LANGSMITH_TRACING"true" export LANGSMITH_API_KEY"..."或者&#xff0c;如果在笔记本中&#xff0c;您可以使用以下命令设置它们 import getpass imp…...

探索 C++23 的 views::cartesian_product

文章目录 一、背景与动机二、基本概念与语法三、使用示例四、特点与优势五、性能与优化六、与 P2374R4 的关系七、编译器支持八、总结 C23 为我们带来了一系列令人兴奋的新特性&#xff0c;其中 views::cartesian_product 是一个非常实用且强大的功能&#xff0c;它允许我们轻…...

【docker】--镜像管理

文章目录 拉取镜像启动镜像为容器连接容器法一法二 保存镜像加载镜像镜像打标签移除镜像 拉取镜像 docker pull mysql:8.0.42启动镜像为容器 docker run -dp 8080:8080 --name container_mysql8.0.42 -e MYSQL_ROOT_PASSWORD123123123 mysql:8.0.42 连接容器 法一 docker e…...

Stapi知识框架

一、Stapi 基础认知 1. 框架定位 自动化API开发框架&#xff1a;专注于快速生成RESTful API 约定优于配置&#xff1a;通过标准化约定减少样板代码 企业级应用支持&#xff1a;适合构建中大型API服务 代码生成导向&#xff1a;显著提升开发效率 2. 核心特性 自动CRUD端点…...

Hapi.js知识框架

一、Hapi.js 基础 1. 核心概念 企业级Node.js框架&#xff1a;由Walmart团队创建&#xff0c;现由社区维护 配置驱动&#xff1a;强调声明式配置而非中间件 插件架构&#xff1a;高度模块化设计 安全优先&#xff1a;内置安全最佳实践 丰富的生态系统&#xff1a;官方维护…...

Node.js 中的 URL 模块

一、URL 模块基础 1. 模块导入方式 // Node.js 方式 const url require(url);// ES 模块方式 (Node.js 14 或启用 ESM) import * as url from url; 2. 核心功能 解析 URL 字符串 格式化 URL 对象 URL 处理工具方法 WHATWG URL 标准实现 二、URL 解析与构建 1. 传统解…...

Java集合框架详解与使用场景示例

Java集合框架是Java标准库中一组用于存储和操作数据的接口和类。它提供了多种数据结构&#xff0c;每种数据结构都有其特定的用途和性能特点。在本文中&#xff0c;我们将详细介绍Java集合框架的主要组成部分&#xff1a;List、Set和Queue&#xff0c;并通过代码示例展示它们的…...

Ensemble Alignment Subspace Adaptation Method for Cross-Scene Classification

用于跨场景分类的集成对齐子空间自适应方法 摘要&#xff1a;本文提出了一种用于跨场景分类的集成对齐子空间自适应&#xff08;EASA&#xff09;方法&#xff0c;它可以解决同谱异物和异谱同物的问题。该算法将集成学习的思想与域自适应&#xff08;DA&#xff09;算法相结合…...

如何通过 Windows 图形界面找到 WSL 主目录

WSL(Windows Subsystem for Linux)是微软开发的一个软件层,用于在 Windows 11 或 10 上原生运行 Linux 二进制可执行文件。当你在 WSL 上安装一个 Linux 发行版时,它会在 Windows 内创建一个 Linux 环境,包括自己的文件系统和主目录。但是,如何通过 Windows 的图形文件资…...

深入 MySQL 查询优化器:Optimizer Trace 分析

目录 一、前言 二、参数详解 optimizer_trace optimizer_trace_features optimizer_trace_max_mem_size optimizer_trace_limit optimizer_trace_offset 三、Optimizer Trace join_preparation join_optimization condition_processing substitute_generated_column…...