在 Linux 上运行 .NET 网站,通过
HttpContext.Connection.RemoteIpAddress
获取客户端的 IP 地址,结果是
::ffff:127.0.0.1
解决方法:
打开 Program.cs 文件,在 var app = builder.Build(); 之前(尽量往前)添加以下代码:
if (OperatingSystem.IsLinux())
{
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor
| ForwardedHeaders.XForwardedProto
| ForwardedHeaders.XForwardedHost;
// 清除 KnownNetworks 和 KnownProxies,表示信任来自本机的代理(如 Nginx)
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
Console.WriteLine("ForwardedHeaders enabled (Running on Linux)");
}
然后在 app.UseRouting(); 之前添加以下代码:
if (OperatingSystem.IsLinux())
{
app.UseForwardedHeaders();
Console.WriteLine("UseForwardedHeaders() applied.");
}
其中,OperatingSystem.IsLinux() 用于判断只在 Linux 环境中生效,你可以视自身情况作判断。

.NET 项目发布到 Linux / CentOS / nginx 上,调用 RedirectToAction 方法跳转到 127.0.0.1:443,而不是正在访问的域名,怎么办?
打开该网站的 nginx 配置文件,找到反射代理配置(proxy_pass),将:
proxy_set_header Host 127.0.0.1:$server_port;
改为
proxy_set_header Host $host;

早前记录过在 CentOS 中部署 ASP.NET Core 网站,现在宝塔面板已经直接支持创建 .NET 网站了,再次记录一下。
本文环境:VS2022、.NET 9、宝塔面板v11。
一、在 VS 中创建一个 .NET 9 网站,项目名称例:WebApplication1
发布选项:
关于“生成单个文件”选项,若勾选,发布后的项目启动文件不带后缀名(.dll),尝试在宝塔面板 v11.0.0 中无法顺利启动。
二、在 Linux 服务器上创建目录:/www/wwwroot/WebApplication1/
将发布后的文件上传到这个目录上,最终的文件结构如下:
三、进入宝塔面板,在 网站-Net项目 中安装 .Net环境管理,这里以 9.0.201 为例:
四、添加项目
项目名称:随意
运行路径:项目所在目录,本例中为:
/www/wwwroot/WebApplication1
启动命令:使用 dotnet 命令,dotnet 命令可以不使用全路径(/www/server/dotnet/9.0.201/dotnet),第一个参数是项目启动文件,--urls 是反向代理的服务器和端口。服务器名可以是*也可以是localhost。例:
dotnet WebApplication1.dll --urls=http://*:5000
项目端口:与启动命令中的端口号一致
开机启动:一般会勾选
启动用户:尽量用 www,最小权限原则。
正常情况下,网站已启动,如果未启动,检查配置,根据报错内容排查问题。
五、配置网站
添加域名、SSL 证书等。
友情提示:
网站版本更新重新发布后,需要手动重启网站才能生效,习惯于发布到 IIS(会自动生效)的同学要特别注意。
新手尽量以空项目或默认项目来部署,避免因特殊原因导致一系列其它问题。
nginx 反向代理并不会转发所有 Header,需要手动配置。

nginx.conf 中使用 resolver 设置了 DNS 后,nginx 会遵循这个指令,而不是直接使用系统的 hosts 配置。
所以,如果 resolver 设置了外部 DNS(譬如一般的公共 DNS),在 access_by_lua_block 中使用 resty.http 库发起对包含域名的网址的请求,会忽略 hosts 的设置。
解决方案:
1、修改 resolver 指向为本机 DNS。(AI 推荐,实测无效,可以研究一下配合 dnsmasq 使读取 hosts)
查看本机 DNS 的命令:
cat /etc/resolv.conf
或
nmcli dev show | grep DNS
2、request_uri 中直接请求带 IP 地址的网址。
要求这个网站允许直接使用 IP 地址访问。
需要禁用 SSL 验证(ssl_verify = false)。

IIS 中使用 HttpPlatformHandler 模块部署 python web 项目时遇到 502.3 网关错误:
HTTP 错误 502.3 - Bad Gateway
There was a connection error while trying to route the request.
最可能的原因:
CGI 应用程序没有返回一组有效的 HTTP 错误。
由于父网关中出现错误,充当代理或网关的服务器无法处理该请求。
可尝试的操作:
使用 DebugDiag 排查 CGI 应用程序。
确定此错误是否由代理或网关引起。
详细错误信息:
模块 httpPlatformHandler
通知 ExecuteRequestHandler
处理程序 httpplatformhandler
错误代码 见下方表格
详细信息:
当 CGI 应用程序未返回一组有效的 HTTP 头,或者代理或网关无法将请求发送至父网关时,便会出现此错误。您可能需要获取一个网络跟踪,或者与代理服务器管理员联系(如果不是 CGI 的问题)。
错误代码 | 可能的错误原因 |
---|---|
0x8007053d | 未安装相关组件库,建议执行命令:pip install -r requirements.txt |
0x80070005 | 若显示配置错误“由于权限不足而无法读取配置文件”则是应用代码目录未配置相应用户的读取权限; 访问受限,请正确配置 IIS 中的网站凭据、应用程序池标识、项目目录“读取”、解释器目录“读取和执行”权限等 |
0x80072ee2 | 执行超时,一般发生在批量读写的时候 |
0x8007042b | |
任何错误 | 查看日志文件。 可能的错误原因:
|

临界区与 lock 关键字
核心作用:
通过将多线程访问串行化,保护共享资源或代码段。lock 关键字是 Monitor 类的语法糖,提供异常安全的临界区实现。
实现示例:
// 创建私有静态只读对象 // private static readonly object _lockObj = new object(); private static readonly System.Threading.Lock _locker = new(); // .NET 9+ 推荐使用 Lock 类型,避免传统 object 的性能损耗 public void ThreadSafeMethod() { lock (_lockObj) { // 临界区代码(每次仅一个线程可进入) } }
超时机制:
高并发场景可结合 Monitor.TryEnter 设置超时,避免无限等待:
if (Monitor.TryEnter(lockObject, TimeSpan.FromSeconds(1))) { try { /* 操作 */ } finally { Monitor.Exit(lockObject); } }
关键特性:
用户态锁(无内核切换开销)
自动调用Monitor.Enter和Monitor.Exit
必须使用专用私有对象作为锁标识
注意事项:
❌ 避免锁定this、Type实例或字符串(易引发死锁)
❌ 避免嵌套锁(需严格按顺序释放)
✅ 推荐readonly修饰锁对象
❌ lock 不适用于异步代码(async/await),需使用 SemaphoreSlim 实现异步锁
互斥锁(Mutex)
核心作用:
系统级内核锁,支持跨进程同步,但性能开销较高(用户态/内核态切换)。
实现示例:
using var mutex = new Mutex(false, "Global\\MyAppMutex"); try { // 等待锁(最大等待时间500ms) if (mutex.WaitOne(500)) { // 临界区代码 } } finally { if (mutex != null) { mutex.ReleaseMutex(); } }
关键特性:
支持跨应用程序域同步
线程终止时自动释放锁
支持命名互斥体(系统全局可见)
适用场景:
单实例应用程序控制
进程间共享文件访问
硬件设备独占访问
信号量(Semaphore)
核心作用:
通过许可计数器控制并发线程数,SemaphoreSlim为轻量级版本(用户态实现)。
实现对比:
类型 跨进程 性能 最大许可数 Semaphore ✔️ 低 系统限制 SemaphoreSlim ❌ 高 Int32.Max 代码示例:
// 创建初始3许可、最大5许可的信号量 var semaphore = new SemaphoreSlim(3, 5); semaphore.Wait(); // 获取许可 try { // 资源访问代码 } finally { semaphore.Release(); }
异步编程
private readonly SemaphoreSlim _asyncLock = new(1, 1); public async Task UpdateAsync() { await _asyncLock.WaitAsync(); try { /* 异步操作 */ } finally { _asyncLock.Release(); } }
典型应用:
数据库连接池(限制最大连接数)
API 请求限流
批量任务并发控制
事件(Event)
核心机制:
通过信号机制实现线程间通知,分为两种类型:
类型 信号重置方式 唤醒线程数 AutoResetEvent 自动 单个 ManualResetEvent 手动 所有 使用示例:
var autoEvent = new AutoResetEvent(false); // 等待线程 Task.Run(() => { autoEvent.WaitOne(); // 收到信号后执行 }); // 信号发送线程 autoEvent.Set(); // 唤醒一个等待线程
高级用法:
配合WaitHandle.WaitAll实现多事件等待
使用ManualResetEventSlim提升性能
读写锁(ReaderWriterLockSlim)
核心优势:
实现读写分离的并发策略,适合读多写少场景(如缓存系统)。
锁模式对比:
模式 并发性 升级支持 读模式(EnterReadLock) 多线程并发读 ❌ 写模式(EnterWriteLock) 独占访问 ❌ 可升级模式 单线程读→写 ✔️ 代码示例:
var rwLock = new ReaderWriterLockSlim(); // 读操作 rwLock.EnterReadLock(); try { // 只读访问 } finally { rwLock.ExitReadLock(); } // 写操作 rwLock.EnterWriteLock(); try { // 排他写入 } finally { rwLock.ExitWriteLock(); }
最佳实践:
优先使用ReaderWriterLockSlim(旧版有死锁风险)
避免长时间持有读锁(可能饿死写线程)
原子操作(Interlocked)
原理:
通过CPU指令实现无锁线程安全操作。
常用方法:
int counter = 0; Interlocked.Increment(ref counter); // 原子递增 Interlocked.Decrement(ref counter); // 原子递减 Interlocked.CompareExchange(ref value, newVal, oldVal); // CAS操作
适用场景:
简单计数器
标志位状态切换
无锁数据结构实现
自旋锁(SpinLock)
核心特点:
通过忙等待(busy-wait)避免上下文切换,适用极短临界区(<1微秒)。
实现示例:
private SpinLock _spinLock = new SpinLock(); public void CriticalOperation() { bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); // 极短临界区代码 } finally { if (lockTaken) _spinLock.Exit(); } }
优化技巧:
单核CPU需调用Thread.SpinWait或Thread.Yield
配合SpinWait结构实现自适应等待
同步机制对比指南
机制 跨进程 开销级别 最佳适用场景 lock ❌ 低 通用临界区保护 Mutex ✔️ 高 进程间资源独占 Semaphore ✔️ 中 并发数限制(跨进程) SemaphoreSlim ❌ 低 并发数限制(进程内) ReaderWriterLockSlim ❌ 中 读多写少场景 SpinLock ❌ 极低 纳秒级临界区 Interlocked - 无锁 简单原子操作
选择原则:
优先考虑用户态锁(lock/SpinLock/SemaphoreSlim)
跨进程需求必须使用内核对象(Mutex/Semaphore)
读写比例超过10:1时考虑读写锁
自旋锁仅用于高频短操作(如链表指针修改)
通过以上结构化的分类和对比,开发者可以更精准地选择适合特定场景的线程同步方案。建议在实际使用中配合性能分析工具(如BenchmarkDotNet)进行量化验证。
💡 ASP.NET 的异步编程(async/await)本质是单进程内的线程调度,不算“跨进程”。每个 IIS 应用程序池对应一个独立的工作进程(w3wp.exe),不同用户访问同一应用程序池下的 ASP.NET 网站,两者的请求均由同一个 w3wp.exe 进程处理。可能跨进程的场景有:Web Garden 配置、多应用程序池部署等。
在 C# 中,除了常规锁机制(如 lock、Mutex、Semaphore 等),还有一些内置类型通过内部锁或无锁设计实现线程安全。以下是常见的几类:
线程安全集合(System.Collections.Concurrent)这些集合通过细粒度锁或无锁算法(如 CAS)实现线程安全,适合高并发场景。
ConcurrentDictionary:分段锁机制,将数据分片存储,每个分片独立加锁,减少锁竞争。
ConcurrentQueue / ConcurrentStack:基于原子操作(Interlocked)保证线程安全。
ConcurrentBag:每个线程维护本地存储,减少争用,适合频繁添加和移除的场景。
BlockingCollection:基于 ConcurrentQueue 和信号量(SemaphoreSlim)实现生产-消费者模式,支持阻塞和超时。
不可变集合(System.Collections.Immutable) 通过数据不可变性实现线程安全(无需锁),每次修改返回新对象。
Lazy 的线程安全初始化(Lazy<T>) 通过锁或 Interlocked 确保延迟初始化的线程安全。
通道(System.Threading.Channels)用于异步生产-消费者模型,内部通过锁和信号量管理容量限制。
内存缓存(System.Runtime.Caching.MemoryCache)内部使用锁保护共享状态,确保线程安全。
原子操作类型(Interlocked 类、Volatile 关键字、Unsafe 类)通过 CPU 指令实现无锁线程安全。
其他同步工具(Barrier、CountdownEvent)虽然不是严格意义上的锁,但用于协调线程。

在 .NET Framework 的缓存管理中,cacheMemoryLimitMegabytes 是一个关键配置属性,用于控制内存缓存(MemoryCache)实例的最大内存占用。以下是其具体用法及实现细节:
基本定义与作用
功能:通过 cacheMemoryLimitMegabytes 可设置 MemoryCache 实例允许占用的最大内存(单位:MB)。若缓存数据超过此限制,系统会自动淘汰旧条目。
默认值:默认值为 0,表示缓存基于计算机的物理内存自动管理(例如根据可用内存动态调整)。
配置方式
通过配置文件(web.config)
在 web.config 的 <system.runtime.caching> 节点下配置 namedCaches,示例:
<configuration> <system.runtime.caching> <memoryCache> <namedCaches> <add name="Default" cacheMemoryLimitMegabytes="500" physicalMemoryLimitPercentage="50" pollingInterval="00:05:00" /> </namedCaches> </memoryCache> </system.runtime.caching> </configuration>
参数说明:
cacheMemoryLimitMegabytes:最大内存限制(例如 500 表示 500MB)。
physicalMemoryLimitPercentage:允许使用的物理内存百分比(可选)。
pollingInterval:缓存清理策略的轮询间隔(例如每5分钟检查一次)。
通过代码动态配置
在初始化 MemoryCache 时,通过 NameValueCollection 传递参数:
var config = new NameValueCollection { { "cacheMemoryLimitMegabytes", "500" }, { "physicalMemoryLimitPercentage", "50" }, { "pollingInterval", "00:05:00" } }; var cache = new MemoryCache("CustomCache", config);
此方式适用于需要动态调整缓存策略的场景。
注意事项
优先级规则:
若同时配置了 cacheMemoryLimitMegabytes 和 physicalMemoryLimitPercentage,系统会选择两者中较小的值作为限制。
分布式缓存兼容性:
此属性仅适用于进程内缓存(如 MemoryCache),若使用 Redis 等分布式缓存需通过其独立配置管理内存。
监控与调试:
建议结合性能计数器(如 ASP.NET Applications 类别下的 Cache Total Entries)或日志记录模块(参考 web.config 的 <system.diagnostics> 配置)监控实际内存占用。
应用场景示例
场景:一个电商网站需要缓存商品目录数据,限制最大内存为 1GB。
配置实现:
<add name="ProductCatalogCache" cacheMemoryLimitMegabytes="1024" pollingInterval="00:10:00" />
代码调用:
var productCatalog = MemoryCache.Default["ProductCatalog"];
常见问题
Q:设置为 0 时缓存会无限制增长吗?
A:不会。此时缓存基于系统物理内存动态管理,通常上限为总内存的 70%-90%。
Q:如何验证配置已生效?
A:可通过 MemoryCache.GetCount() 统计条目数量,或使用性能监视器跟踪内存占用。

数据库 | 数据类型 | 收费情况 | 调用方式 | 数据来源 | 资料 |
---|---|---|---|---|---|
BaoStock | 仅提供历史数据(如日线、周线),无实时行情 | 免费开源 | Python | 数据来源为交易所或合作机构的标准化接口 | 文档 |
AkShare | 股票、期货、债券、期权、外汇、货币、指数…… | 免费开源 | Python / Anaconda / R / MATLAB / 本地 Web API |
基于爬虫技术从大型财经网站抓取公开数据 包含北交所行情数据 |
文档 / 数据字典 / AKTools |
Tushare Pro | 股票、指数、公募、期货、期权、债券、外汇、港股、美股…… | 免费 / 收费 | Web API / Python / Matlab / R |
通过社区的采集和整理存入数据库经过质量控制后再提供给用户 包含北交所行情数据 |
积分 / 权限 / 文档 |
麦蕊智数 | 沪深股票基础数据、实时交易数据、指数数据 | 免费 / 收费 | Web API | licence / 文档 | |
JoinQuant/JQData | 股票、基金等行情数据 | 试用 / 收费 | Python | 文档 |

国家智慧教育公共服务平台 https://gjzwfw.www.gov.cn/
中国裁判文书网 https://wenshu.court.gov.cn/
国家企业信用信息公示系统 https://gs.gsxt.gov.cn/
国家社会保险服务平台 https://si.12333.gov.cn/
国家法律法规数据库 https://flk.npc.gov.cn/
中国专利公布公告网 http://epub.cnipa.gov.cn/
国家标准全文公开系统 https://openstd.samr.gov.cn/bzgk/gb/
国家药品监督管理局 https://www.nmpa.gov.cn/datasearch/
食品安全抽检公布结果查询系统 https://spcjsac.gsxt.gov.cn/
工信部申诉受理中心 https://ythzxfw.miit.gov.cn/
合同示范文本库 https://htsfwb.samr.gov.cn/
中国法律服务网 https://www.12348.gov.cn/
中国庭审公开网 https://tingshen.court.gov.cn/
非 gov 网站
终身教育平台 https://le.ouchn.cn/
国家数字图书馆 https://www.nlc.cn/
国家哲学社会科学文献 https://www.ncpssd.cn/
国家高等教育智慧教育平台 https://www.chinaooc.com.cn/
职业教育专业教学资源库 https://zyk.icve.com.cn/
本文仅针对自己遇到的情况进行整理,并不完善,仅供参考。
首先点击这个封禁页面上的“客服指引”,在“微信访问网站被限制的相关问题”页面上找到反馈邮箱 moment@tencent.com,按规定格式给这个邮箱反馈情况,可以咨询具体被封禁的原因和网址等方便处理。几分钟后就能收到回信(即使是周末)。这次被告知是被手机管家拦截,并提供了另一个申述通道:http://gj.qq.com/online_server/complain_url.html。提交网址申述后等待3个工作日。
实际等了1个小时就收到回复了(即使是周末)。
附:在线网址检测:https://urlsec.qq.com/check.html
