C#委托之Action和Func的用法

我们在使用委托的过程中,除了为每个参数和返回类型定义一个委托之外,也就是说为每一个方法(作为参数的方法)定义一个委托,我们还可以使用Action和Func委托。 泛型Action委托表示引用一个void返回类型的方法。Action委托类存在不同的变体,可以传递至多16种不同的参数类型,没有泛型参数的Action类可以调用没有参数的方法。例如:Action调用带一个参数的方法,Action<in T1,in T2>调用带两个参数的方法等 Func的用法和Action用法类似,但是Func表示引用一个带返回类型的方法,Func也存在不同的变体,至多可以传递16个参数类型和1个返回类型,例如:Func<in T1,out Resout>表示带一个参数的方法,Func<in T1,in T2,out Resout>表示调用带两个参数的方法。 总结 1:Action用于没有返回值的方法(参数可以根据自己情况进行传递);2:Func恰恰相反用于有返回值的方法(同样参数根据自己情况情况);3:记住无返回就用action,有返回就用Func

October 20, 2022

[转]Azure Container App 应用介绍

容器技术正日益成为打包、部署应用程序的第一选择。Azure提供了许多使用容器的选项。例如,我们可以使用Azure容器注册表来存储和管理Docker Images。Azure Container Instance或Azure应用服务可用于运行隔离容器。对于需要完整容器编排、自动缩放和服务发现的更复杂的场景,Azure Kubernetes服务是一个很好的选择。问题是,Azure Kubernetes虽然是托管的,但 用起来还是有些困难,开发人员必须得学习掌握一些运维知识。 2021年,Azure提出了新服务 Azure Container App。该服务旨在减少构建 AKS 应用程序所需的知识和配置量,从而可能降低解决方案成本并加快上市时间。 1,什么是 Azure Container App ?? Azure Container App 提供位于 AKS 服务之上的无服务器托管服务,允许您部署多个容器而无需处理底层基础结构。事实上,Azure Container App 甚至不向用户公开 Kubernetes API。 当我们在 Azure Container App中部署或更改容器时,该服务将自动创建应用程序的快照—–修订版,并在一个 pod 中运行它的容器。就像在 Azure Kubernetes 中一样,这些容器共享相同的应用程序生命周期、网络和磁盘。它们可以相互交流。此外,由于它与基于 Kubernetes 的事件驱动自动缩放的集成,该服务将根据 HTTP 并发请求数等指标自动增加/减少(不支持垂直缩放)与修订相关的 Pod 数量和内存使用。作为节省一些费用上开支,我们还可以将最小副本数设置为 0。如果应用程序没有请求,该服务会将活动 pod 的数量缩减为 0,我们无需支付任何费用。 同时多个 Azure Container App 也可以部署到单个环境中。通过这样做,它们将被置于同一个虚拟网络下并与外界隔离。为了提供监视功能,每个环境都有自己的 Log Analytics 工作区,该工作区与其中的 Azure Container App共享。对于熟悉 Kubernetes 的人来说,我们可以将 Azure Container App Environment 视为 Kubernetes Namespace,将 Azure Container App Revision 视为 Kubernetes Deployment。 ...

October 10, 2022

依赖注入简单易懂的详解

之前记录的依赖注入太复杂,今天认真看了《C#高级编程》里面对依赖注入的解释,明显就简单很多。 1、什么是依赖注入?为什么需要它? 更快的开发周期需要单元测试和更好的可更新性。更改一些代码,不应该导致意外位罝出现错误。创建更模块化的、减少依赖项的应用程序,有助于防止这种错误。 依赖注入(Dependency Injection,DI)允许从类的外部注入依赖项,因此注入依赖项的类只需要知道一个协定(通常是C#接口)。这个类可以独立于其对象的创建。 依赖注入更便于进行单元测试。在单元测试中,只需要测试特定的类,需要的依赖项可以替换为包含测试数据的特殊模拟类。 还可以使用不同的实现区分生产模式和开发模式。例如,在生产过程中,可能需要访问SAP服务器,或者可能需要对所有开发人员都无法访问的特定活动目录进行身份验证。在开发的每个调试会话期间,都不希望等待成功的身份验证,也不需要SAP服务器开发用户界面。在这里,可以给相同的协定使用不同的实现来模拟身份验证,可以使用测试数据而不是访问SAP服务器。 也可以在不同的平台上使用不同的实现。例如,可以创建一个.NET标准库,在其中为UWP、WPF和Xamarin应用程序实现所有公共功能,并可以根据需要重定向到特定于平台的代码。 依赖注入还允许用自定义特性替换标准功能。ASP.NETCore和EntityFrameworkCore主要基于依赖注入。这些技术使用数百个协定一例如,来找到控制器,将HTTP请求映射到控制器,将接收到的数据转换为参数,将数据库表映射到实体类型等。使用不同的实现,可以轻松地替换自定义功能。 DI是敏捷软件开发和持续软件交付实践的核心模式。 **依赖注入不需要依赖注入容器,但该容器有助于管理依赖项。**依赖注入容器管理的服务列表越来越长,就可以看到它的优点。ASP.NETCore和EntityFrameworkCore使用Microsoft.Exteosions.DependencyInjection作为容器来管理所有依赖项,以此管理数百个服务。 尽管依赖注入和依赖注入容器在非常小的应用程序中会增加复杂性,但是一旦应用程序变得更大,需要多个服务,依赖注入就会降低复杂性,并促进非紧密绑定的实现。 2、没有依赖注入 下面的示例没有使用依赖注入;稍后将更改它,以使用依赖注入。所用的服务实现在类GreetingService中定义。这个类定义了返回字符串的Greet方法: public class GreetingService { public string Greet(stringname)=>$"Hello,{name}"; } 类HomeController使用这个服务。在Hello方法中,实例化了GreetingService,并且调用Greet方法: public class HomeController { public string Hello(string name) { var service = new GreetingService(); return service.Greet(name); } } 下面看看Program类的Main()方法。其中实例化了HomeController,调用Hello方法,将结果写入控制台: static void Main() { var controller=new HomeController(); string result=controller.Hello("Stephanie"); Console.WriteLine(result); } 程序运行时,把Hello,Stephanie写入控制台。这有什么问题吗? **HomeController和GreetingService是紧密稱合的。要用不同的实现取代HomeController中的GreetingService并不容易。**这个GreetingService是一个返回字符串的简单服务。在正常的应用程序中,场景通常更复杂。例如,GreetingService可能使用HTTP请求访问API服务,或者使用EntityFramewoik访问数据库。可能要更改在一个地方使用的服务,而不是査找使用服务的所有位置。 另外,为HomeController创建单元测试时,也会测试GreetingService。在单元测试中,希望仅测试单个类的方法的功能,而不需要使用其他依赖项。在HomeController中,不能很容易地为单元测试替换GreetingService。从技术上讲,为单元测试替换GreetingService方法的内部实现是可能的。使用Microsoft Fakes框架,可以通过替换GreetingSeivice类的特定方法和属性,来更改方法的实现。这个变更是在单元测试中定义的,并且只有在单元测试运行时才会发生:通过另一个方法来“伪造”原来的方法。其实这有更好的方法:使用依赖注入。 下一节将介绍如何更改此实现,以使用依赖注入。 3、使用依赖注入实现 下面使HomeController独立于GreetingService的实现。为此,可以创建接口IGreetingService,它定义了HomeController所需的功能: public interface IGreetingService { string Greet(stringname); } GreetingService现在实现了接口IGreetingService: public class GreetingService:IGreetingService { public string Greet(stringname)=>$"Hello,{name}"; } HomeController现在只需要对一个对象的引用,该对象实现了接口IGreetingService。它用HomeController的构造函数注入,分配给私有字段,通过方法Hello来使用: public class HomeController { private readonly IGreetingService _greetingService; public HomeController(IGreetingService greetingService) { _greetingService=greetingService?? throw new ArgumentMullException(nameof(greetingService)); } public string Hello(stringname) => _greetingService.Greet(name); } 在这个实现中,HomeController利用了控制反转的设计原理。HomeController没有像以前那样实例化GreetingService。相反,定义由HomeController使用的具体类的控件在外部给出;换句话说,控制是反转的。 ...

September 9, 2022

https请求报错block:mixed-content

开发过程中,可能会遇到在https里面请求内容的时候报混合调用的错误,一般是因为网站启用了https,但是老的网页链接和请求中还有使用http的情况。接口会错block: mixed-content,图片则会报错:Mixed block。解决的办法有两种。 第一种, 页面的head中加入下面代码(将调用的http请求升级成https请求并调用): <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 这是最方便快捷的,也是很有效的办法。 第二种, 如果是接口,可以通过本地后端(将本地后端当成service中间层),从后端再去调用其他服务器的http请求。

September 5, 2022

如何在.NET Core3.1使用log4net

1、添加log4net程序集 通过nuget添加,可以直接在程序集引用里搜索nuget包安装,也可以通过命令行安装,这里使用命令行:PM> Install-Package log4net 2、添加log4net.config配置文件 创建一个log4net.config文件,保存在项目的根目录: <log4net> <root> <level value="ALL" /> <appender-ref ref="console" /> <appender-ref ref="file" /> </root> <!--File Appender--> <appender name="file" type="log4net.Appender.RollingFileAppender"> <file value="main.log" /> <appendToFile value="true" /> <rollingStyle value="Size" /> <maxSizeRollBackups value="5" /> <maximumFileSize value="25MB" /> <staticLogFileName value="true" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %level %logger - %message%newline" /> </layout> </appender> <!--Console appender--> <appender name="console" type="log4net.Appender.ManagedColoredConsoleAppender"> <mapping> <level value="INFO" /> <forecolor value="Green" /> </mapping> <mapping> <level value="WARN" /> <forecolor value="Yellow" /> </mapping> <mapping> <level value="ERROR" /> <forecolor value="Red" /> </mapping> <mapping> <level value="DEBUG" /> <forecolor value="Blue" /> </mapping> <layout type="log4net.Layout.PatternLayout"> <conversionpattern value="%date [%thread] %-5level - %message%newline" /> </layout> </appender> </log4net> 3、加载log4net的配置的并创建相关实例 这里有两种办法,第一种最简单,这种情况适用于控制台应用程序,简单明了,直接用加载到程序集中: ...

August 23, 2022

ABP框架能力清单

ABP框架提供了一个稳定的架构用于构建企业级软件解决方案,它遵循了.NET和ASP.NETCore平台之上的最佳实践。它内置了基础架构、生产级别的模块、主题、工具、指南和文档,并尽可能地自动化开发细节和解法我们的重复性工作。 在接下来的几个小节中,我将从架构层面介绍ABP是如何完成所有这些工作。 ABP架构 ABP是一个特殊的架构,换句话说,它是一个有个性化的框架。先解释一下什么是没有个性的框架,什么是有个性的框架。 正如我在搭建架构部分所述,为搭建解决方案的基础设施需要大量决策工作;比如系统架构、开发模型、技术、模式、工具和库。 没有个性的框架,例如ASP.NETCore,这些决定大多由您决定。例如,您可以通过将UI层与数据访问层分离来创建分层解决方案,或者您可以通过直接从UI页面/视图访问数据库来创建单层解决方案。您可以使用任何库,只要它与ASP.NETCore兼容,并且您可以应用任何架构模式。无个性使ASP.NETCore在不同的场景中变得灵活和可用。但是,所有的这些都需要我们自己去做决策。 我并不是说ASP.NETCore完全没有自己的个性想法。假定您正在构建基于HTTP规范的Web应用程序或API。它清楚地定义了应该如何开发UI和API层。它还提供了一些低级的基础设施组件,例如依赖项注入、缓存和日志记录。但是,它并没有说明您的业务代码是应该要如何组建,应该使用哪些架构模式。 换句话说,ABP框架是一个有个性倾向的框架。它相信软件开发方法本质上可以更好,因此可以引导开发人员在解决方案中使用更佳的架构、模式、工具和库。 尽管ABP框架足够灵活,可以使用不同的工具和库来改变您的架构决策,但当您遵循它的实践原则时,您将获得最大的价值。请别担心,因为它为通用架构提供了良好的、行业认可的解决方案。他的架构规则将节省您的时间,提高您的生产力,并使您专注于您的业务代码而不是基础设施问题。 在接下来,我将介绍ABP所支持的四种基本架构。 领域驱动设计 ABP的主要目标是根据整洁代码原则提供一个模型来构建易维护的解决方案。它提供了一个基于DDD模式和实践的分层架构。它提供了一个分层的启动模板、基础架构以及架构应用指南。 由于ABP是一个软件框架,它专注于DDD的技术实现。本书的第3部分,实现领域驱动设计,解释了使用ABP框架构建基于DDD的最佳实践。 模块化 在软件开发中,模块化是一种拆分系统成独立模块的技术。最终目标是降低复杂性,提高可重用性,使不同的团队能够在不相互影响的情况下能并行处理不同的功能集。 ABP构建模块化有两个主要挑战: 第一个挑战是模块隔离。尽管ASP.NETCore有一些特性(例如Razor组件库)来支持模块化。但是,它仍然非常有限,因为它是一个底层通用的框架,并且仅对UI和API部分支持。另一方面,ABP框架提供了一个一致的模型和基础设施来构建完全隔离的、可重用的应用模块及数据库、领域、应用和UI层。 第二个挑战是模块之间如何通信,使之成为一个统一的应用程序。ABP为模块化系统提供常见的模型,例如在模块之间共享数据库,在模块之间通过事件或API进行通信,以及模块安装。 ABP提供了许多可在任何应用程序中使用的预构建模块。包括身份验证模块,它提供用户、角色和权限管理,同时也提供登录和注册页面。他们基本上都是可重用和自定义的。此外,ABP提供了模块启动模板,帮助您构建可重用的应用程序。这方面的一个例子可以在[第15章]使用模块化中详细介绍。 模块化非常适合管理复杂的大型单体系统。但是,ABP也可以帮助您创建微服务解决方案。 微服务 微服务和分布式架构是构建可扩展系统的公认方法。它允许不同的团队开发不同的服务并独立地对服务进行单独部署和扩展。 但是,构建微服务系统在团队开发、部署、微服务间通信、数据一致性、监控等方面存在一些重要挑战。 微服务系统是一种将不同的学科、方法、技术和工具结合在一起来解决独特问题的解决方案。每个微服务系统都有其要求和限制。每个团队都有一定程度的专业知识、知识和技能。 ABP框架从一开始就被设计为与微服务兼容。它在具有事务支持的微服务之间提供了一个用于异步通信的分布式事件总线。它还提供C#客户端代理来轻松调用远程服务的RESTAPI。 所有预构建的ABP应用模块都经过设计,以便您可以将它们转换为微服务。ABP也提供了详细指南来解释如何创建微服务兼容模块。这样,您可以从模块化单体开始,然后将其转换为微服务解决方案。 ABP团队准备了一个使用ABP框架构建的开源微服务参考方案。它演示了如何使用API网关、微服务间通信、分布式事件、分布式缓存、多个数据库提供程序和多个UI应用程序。它还包括在容器上运行解决方案的Kubernetes和Helm配置。详情参阅。 SaaS/多租户 软件即服务(SaaS)是一种广泛使用的架构模式。以下是多租户系统的典型特征: 在租户之间共享硬件和软件资源。每个租户都有用户、角色和权限。在租户之间隔离数据库、缓存和其他资源。可以启用/禁用每个租户的应用功能。可以为每个租户自定义应用配置。 ABP框架涵盖了所有这些要求甚至更多。它可以帮助您优雅地构建多租户系统,而您几乎感受不到多租户的存在。 到目前为止,我已经介绍了四种ABP基本架构模式。此外,ABP还提供了启动模板来轻松创建新的解决方案。 启动模板 使用ASP.NETCore自带的模板创建新解决方案时,只能获得单个项目,没有分层和依赖关系。您通常会花费大量时间来设置解决方案架构,包括安装工具和做配置基本。 ABP框架提供了一个架构完善、分层清晰、预配置和生产就绪的启动解决方案模板。以下截图显示了当您运行ABP框架创建的启动模板时的初始UI: 下面谈谈这个启动模板:解决方案已经做好逻辑分层。一些预构建模块,例如Account和Identity模块。已经实现了基本的登录、注册、用户和角色管理以及其他一些标准功能。预先配置好的单元测试和集成测试项目。一些管理数据库迁移以及使用HTTPAPI实用工具。 ABP的启动模板带有UI框架和数据库提供者的多个选项。你可以从Angular、Blazor或MVC(RazorPages)选择一个作为UI框架,或者使用EntityFrameworkCore或MongoDB作为数据库提供者。 ABP基础设施 ABP基于您已经了熟悉的工具和库。它没有引入新的对象关系映射器(ORM),而是使用EntityFrameworkCore。同样,它使用Serilog、AutoMapper、IdentityServer和Bootstrap,而不是自己创建类似的功能。它提供了一个解决方案集成了这些工具,并实现了常见的业务应用需求。 ABP框架按照约定简化了异常处理、验证、授权、缓存、审计日志和数据库事务管理,并允许您在需要时进行精细控制。 ABP与IdentityServer很好地集成,基于cookie和令牌的身份验证以及单点登录。它还提供了一个详细的、基于权限的授权系统来帮助您控制应用的权限。 同时也提供了后台作业、BLOB存储、文本模板、审计日志和本地化等常见组件。 在UI部分,ABP提供了完整的UI主题系统,帮助您开发无主题的模块化应用,并轻松为应用程序安装主题。它还在UI方面提供了大量功能和帮助程序,以消除重复代码。 社区 当您在公司中搭建解决方案架构时,除了开发人员没有人会去研究它。然而,ABP拥有一个庞大而活跃的社区。他们使用相同的架构和基础设施,应用类似的最佳实践,并以类似的方式开发他们的应用程序。当您遇到基础架构问题或想要获得解决业务问题的想法或建议时,这具有很大的优势。由于ABP开发人员正在应用相同或相似的模式,因此在另一个解决方案中也更容易理解他人的代码。 ABP框架自2016年以来一直存在并不断发展。截至2021年底,它在GitHub上拥有7,000多颗星、220多位贡献者、22,000多个提交、5,700个已关闭问题,以及在NuGet上超过4,000,000次下载,超过110多个专业和次要版本。我的意思是,它是一个成熟的、被接受的、值得信赖的开源项目。 来自ABP核心团队和社区的贡献者,有着不断持续输出的文章,视频教程和ABP社区网站可供大家学习。

July 8, 2022

ASP.NET Core应用程序配合web服务器的工作原理

这段时间开始阅读.NET Core内部技术的书籍,发现了很多之前忽视的技术,果然还是得通过阅读,才可以加深对技术的理解。今天了解到了ASP.NET Core应用程序配合web服务器的工作原理。 Web服务器(如IIS)通过一个配置的端口与完全解耦的可执行文件通信,并将传入的请求转发给控制台应用程序。这个控制台应用程序由一个必要的HTTP模块从US进程空间生成,该HTTP模块使IIS能够支持ASP.NETCore。要将ASP.NETCore应用程序托管到其他Web服务器(如Apache或NGINX)上,必须有类似的扩展模块。 这里值得注意的是,图中给出的ASP.NETCore架构与最初的架构(即2003年将ASP.NET1.x与IIS连接起来的架构)有类似之处。当时ASP.NET有自己的工作进程,通过命名管道与IIS通信。后来,ASP.NET工作进程的任务被内置的IIS工作进程(w3wp.exe)接过,从而有了应用程序池的概念。在ASP.NETCore中,两个独立的、无关的、完全解耦的可执行文件进行通信,但是ASP.NET可执行文件并不是一个多租户工作进程,而只是托管一个基本的异步服务器来处理传入请求的应用程序的一个实例。

June 28, 2022

微软官方.NET 升级助手:可以将NET Core 3.1项目升级为.NET 6

装并运行升级助手 在命令提示符下,运行以下命令安装升级助手工具: dotnet tool install -g –add-source ‘https://api.nuget.org/v3/index.json’ –ignore-failed-sources upgrade-assistant 现在,你已准备好在解决方案或项目上运行该工具。让我们先分析项目的包依赖项。 导航到包含项目或解决方案的目录,并运行以下命令: upgrade-assistant analyze 将此页命令上的 更改为解决方案或项目文件的路径和名称。 上一个命令将生成 SARIF 格式的报告,该报告基于 JSON 格式,可使用以下查看器查看: 任何文本编辑器。 VS extension for SARIF Viewer for a richer experience. 分析项目依赖项后,运行以下命令以开始升级项目: upgrade-assistant upgrade 该工具还支持其他选项。有关完整的工具使用情况信息,请参阅 GitHub 上的 升级助手自述文件。

June 21, 2022

[转]开源框架Autofac使用入门

一、Autofac是什么 说到Autofac,我们就要首先了解依赖注入(Dependency Injection,简称DI)。DI不是什么技术,而是一种设计模式,是用来降低计算机程序之间的耦合的。在.net平台,有很多依赖注入工具,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,Autofac是一款较为轻量级的、性能优异的、支持xml配置的依赖注入工具。这也是为什么我选择先学习Autofac的原因。 1.1 依赖注入(DI)和控制反转(IOC) 依赖注入(Dependency Injection)DI是一种软件设计模式,用来允许我们开发松耦合代码。DI是一种很好的方式去减少软件模块之间的紧耦合关心。DI帮助更好的去管理软件中的功能更新和复杂度。DI的目的是让代码可维护。依赖注入模式使用构造器对对象初始化并提供需要的依赖给对象,也就意味着允许你从类外部注入一个依赖项。 控制反转(IOC,Inversion Of Contrl)也是一种设计模式,它是对DIP(依赖倒置原则,Dependence Inversion Principle)的一种实现。IOC指的是一种框架或运行时的编程风格,用来控制程序流程。IOC意味着我们可以改变常规的控制方式。它在DIP下得以实现。许多基于.net框架的软件开发都使用IOC。IOC更多的是一个通用术语,不仅仅局限于DI。 1.2 DI和IOC在项目中起到什么作用 假设你的客户端类需要使用一个服务类组件,那么你能做的就是让你的客户知道一类IService接口而不是服务类。这样,你就可以随时改变Service类的实现而不会中断已经部署的代码。 二、Autofac如何使用 首先你必须获取AutoFac,这里你可以通过各种方式加载它,我这里还是通过VS中的NuGet来加载AutoFac,不论是哪种方式,最终的目的就是将 Autofac.dll,Autofac.Configuration.dll 这两个程序集引用到你的项目中。这样在你的项目中,如果想使用AutoFac,只需添加其命名空间引用即可~ 这里我用的是2.6版本的(PS:Autofac.Configuration.dll V4.1 已经没有ConfigurationSettingsReader 用法稍有改变,还没去研究) 2.1 Demo分析 代码Demo,这里在控制台应用程序中使用,首先创建一个类 /// <summary> /// 定义一个Animal接口 /// </summary> public interface IAnimal { void DogCall(); void CatCall(); } 然后,写一个类继承此接口 public class Call: IAnimal { public void CatCall() { Console.WriteLine("喵喵喵"); } public void DogCall() { Console.WriteLine("汪汪汪"); } } 接着,用Autofac static void Main(string[] args) { var builder = new ContainerBuilder();//创建一个IOC容器 builder.RegisterType<Call>().As<IAnimal>();//通过AS可以让Call类中通过构造函数依赖注入类型相应的接口。 //Build()方法生成一个对应的Container实例,这样,就可以通过Resolve解析到注册的类型实例。 using (var container = builder.Build()) { //当注册的类型在相应得到的容器中可以Resolve你的Call类中所有实例。 var call = container.Resolve<IAnimal>(); call.DogCall(); call.CatCall(); } Console.ReadLine(); } 使用Autofac的步骤:第一步,定义一个Container容器。第二步,创建builder,并在builder中注册类型。第三步,实例化容器。第四步,在需要使用接口的地方,通过container来解析得到一个借口的实例。 ...

October 22, 2021

关于HTTP请求头中的Remote_Addr,X-Forwarded-For,X-Real-IP值

开发过程中,我们有时候需要获取用户的客户端机器的ip地址,在遥远的拨号上网年代,我们只需要通过很简单的Remote_Addr就能获得客户端的真是ip地址,可是随着代理服务器的普及,客户端的ip地址往往不那么容易拿到。 一、Remote_Addr 这个值表示发出请求的远程主机的IP地址,remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。 二、x_forwarded_for 简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项,正如上面所述,当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,把连接它的客户端IP(即你的上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP。 设置格式:X-Forwarded-For: 127.0.0.1, 192.168.1.1, 202.19.89.64 这个设置表示请求由127.0.0.1发出,经过三层代理,第一层是192.168.1.1,第二层是202.19.89.64,而本次请求的来源IP 1.1.1.1是第三层代理。 三、X-Real-IP 当有多个代理时候,可以在第一个反向代理上配置“proxy_set_header X-Real-IP $remote_addr” 获取真实客户端IP; 四、案例分析 (一)、第一种情况 Nginx Proxy 202.19.89.64 nginx.conf location /test { proxy_pass http://192.168.108.1; } 192.168.108.1 nginx.conf location /test { proxy_pass http://192.168.108.2; } Nginx Proxy就是简单的把请求往后转发。 Nginx Backend 192.168.108.108 nginx.conf location /test { default_type text/html; charset gbk; echo "$remote_addr || $http_x_forwarded_for"; } Nginx Backend输出客户端IP($remote_addr)和X-Forwarded-For请求头($http_x_forwarded_for),当访问服务时输出结果:192.168.108.108 || 1.$remote_addr代表客户端IP,当前配置的输出结果为最后一个代理服务器的IP,并不是真实客户端IP; 2.在没有特殊配置情况下,X-Forwarded-For请求头不会自动添加到请求头中,即Nginx Backend的$http_x_forwarded_for输出为空。 (二)、第二种情况 通过添加X-Real-IP和X-Forwarded-For捕获客户端真实IP。 Nginx Proxy 202.19.89.64 nginx.conf location /test { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.108.1; } 192.168.108.1 nginx.conf location /test { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.108.2; } Nginx Backend 192.168.108.108 nginx.conf location /test { default_type text/html; charset gbk; echo "$remote_addr ||$http_x_real_ip ||$http_x_forwarded_for"; } 当访问服务时,输出结果为:192.168.108.108 || 202.19.89.64 || 192.168.108.1, 192.168.108.2 ...

August 17, 2021