.Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享
前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docker+k8s实现分布式Session共享之前,就先介绍一下IIS+nginx实现Session共享的方案,两者其实区别不大,所以这篇着重介绍方案,下篇介绍测试的区别以及填坑的方式。
1、环境准备
操作系统:Windows10
IIS:需要安装模块
VS2019、本地Redis数据库、ngnix(windows版)
2、Session共享的简易说明
下图简要说明了负载均衡通过轮询方式,将同一个客户端请求发送到不同的站点下,操作的Session应该是同一个。
3、添加测试项目
虽然个人认为本来WebApi中使用Session本身就是一种不合理的设计,但这是旧项目迁移需要保留的历史逻辑,所以只能硬着头皮寻找对应的解决方案了。
在VS2019中添加一个.net core 的WebApi项目,使用Session的话需要添加以下配置。
Startup.cs类中,ConfigureServices方法添加services.AddSession(); Configure方法中添加app.UseSession(); 注意要放到UseMVC方法前面。
测试代码如下,添加testController类,在Get1方法中设置Session,记录当前时间,Get2方法中读取Session
[Route("[action]")]
[ApiController]
public class testController : ControllerBase
{
// GET: api/test
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", HttpContext.Connection.LocalIpAddress.ToString(), HttpContext.Connection.LocalPort.ToString()};
} // GET: api/test/5
[HttpGet]
public string Get1(int temp1)
{
if (string.IsNullOrEmpty(HttpContext.Session.GetString("qqq")))
{
HttpContext.Session.SetString("qqq", DateTime.Now.ToString());
}
return HttpContext.Connection.LocalIpAddress.ToString() + "|" + HttpContext.Connection.LocalPort.ToString();
} [HttpGet]
public string Get2(int temp1, int temp2)
{
return HttpContext.Connection.LocalIpAddress.ToString() + "|" + HttpContext.Connection.LocalPort.ToString() + "|" + HttpContext.Session.GetString("qqq");
}
}
4、发布.net core项目到IIS
(1)右键项目点击发布
(2)记录下发布路径,并在IIS中新增两个站点,指向该路径,并设置不同的端口号
记得把应用程序池中改为无托管代码
5、nginx配置负载均衡
下载地址:http://nginx.org/
配置方式:
(1)找到nginx的安装路径,打开nginx.conf文件
(2)添加upstream配置,配置用于负载均衡轮询的站点,即上一步骤中添加的两个站点
(3)配置location节点,注意proxy_pass与upstream中配置的名称保持一致。
(4)启动ngnix,用cmd命令指定nginx的安装目录,然后start nginx
6、在没有做Session共享方案的情况下进行测试
浏览器分别输入http://localhost:7665/Get1与http://localhost:7665/Get2,由于ip是一样的,所以没有参考必要,不停刷新http://localhost:7665/Get1,最后看到的端口号在7666与7667之间不停的来回切换,说明nginx的轮询是成功的。当然这里只是为了实现session共享做的负载均衡,所以把负载均衡放在了同一台服务器上进行配置,感兴趣的同学可以使用不同服务器配置负载均衡,并用压力测试工具测试站点在配置负载均衡的吞吐能力,后面有机会我可以单独介绍这部分内容。
测试结果:
1、过程: 请求http://localhost:7665/Get1,请求分发到站点7667,设置了Session;
请求http://localhost:7665/Get2,请求分发到站点7666,读取不到该Session;
再次请求Get2,请求分发到站点7667,可以读取到Session。
结论:说明负载均衡的两个站点之间不会读取同一个Session,也就是说Session不会共享。
2、 过程: 再次请求Get1,请求分发到站点7666;
再次请求Get2,请求分发到站点7667,读取不到该Session;
再次请求Get2,请求分发到站点7666,可以读取到Session,且session值被刷新。
结论:因为nginx每次都将请求分发到另外一站点,且session没有共享,所以string.IsNullOrEmpty(HttpContext.Session.GetString("qqq"))总是true,然后session都会被刷新,另一个站点的session就丢失了(这里的丢失应该是刷新session后产生了新的cookie值,导致原来的session无法读取,感兴趣的同学还可以用Fiddler跟踪记录下Get1产生cookie值,然后在Get2请求时带上cookie进行验证)。
7、使用Redis将Session存放在Redis服务器
(1)在Startup.cs文件中,ConfigureServices方法加入以下代码
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false; //这里要改为false,默认是true,true的时候session无效
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
}); services.AddDataProtection(configure =>
{
configure.ApplicationDiscriminator = "wxweb";
})
.SetApplicationName("wxweb")
.AddKeyManagementOptions(options =>
{
//配置自定义XmlRepository
options.XmlRepository = new SessionShare();
}); #region 使用Redis保存Session
// 这里取连接字符串
services.AddDistributedRedisCache(option =>
{
//redis 连接字符串
option.Configuration = Configuration.GetValue<string>("RedisConnectionStrings");
//redis 实例名
option.InstanceName = "Wx_Session";
}); //添加session 设置过期时长分钟
//var sessionOutTime = con.ConnectionConfig.ConnectionRedis.SessionTimeOut;
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(Convert.ToDouble( * * )); //session活期时间
options.Cookie.HttpOnly = true;//设为httponly
});
#endregion
简要说明:
services.Configure<CookiePolicyOptions>是为了可以使用cookie
SetApplicationName("wxweb")是为了保证不同站点下的应用程序名称是一致的。
options.XmlRepository = new SessionShare();是为了保证不同站点下应用程序使用的machinekey是一样的,详情见https://www.cnblogs.com/newP/p/6518918.html
AddDistributedRedisCache是一个官方的拓展组件,用户将session保存在redis中。
RedisConnectionStrings是Redis连接字符串
(2)SessionShare的实现如下
public class SessionShare : IXmlRepository
{
private readonly string keyContent =
@"自己的machinekey"; public virtual IReadOnlyCollection<XElement> GetAllElements()
{
return GetAllElementsCore().ToList().AsReadOnly();
} private IEnumerable<XElement> GetAllElementsCore()
{
yield return XElement.Parse(keyContent);
}
public virtual void StoreElement(XElement element, string friendlyName)
{
if (element == null)
{
throw new ArgumentNullException(nameof(element));
}
StoreElementCore(element, friendlyName);
} private void StoreElementCore(XElement element, string filename)
{
}
}
(3)再次进行发布
8、添加Session共享方案以后进行测试
测试结果:无论Get1刷新多少次,Get2都能拿到Session值,且Session没有被刷新(当前时间没有变化),即Session共享成功。
总结:以前总是看别人的文章了解Session共享,这次自己从配置负载均衡到解决Session共享从头到尾走了一遍,所以记录了下来。下篇文章我会介绍AddDistributedRedisCached在并发量较高时timeout的解决方案。
参考文章(同时感谢这些大佬的文章提供的帮助)
2、Session分布式共享 = Session + Redis + Nginx
.Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享的更多相关文章
- net core+Redis+IIS+nginx实现Session共享
.Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享 前言:虽说公司app后端使用的是.net core+Redis+docker+ ...
- .Net Core Web Api实践(三).net core+Redis+docker实现Session共享
前言:上篇文章介绍了.net core+Redis+IIS+nginx实现Session共享,本来打算直接说明后续填坑过程,但毕竟好多坑是用docker部署后出现的,原计划简单提一下.net core ...
- .Net Core Web Api实践(四)填坑连接Redis时Timeout performing EVAL
前言:前两篇文章.net core+Redis+IIS+nginx实现Session共享中,介绍了使用Microsoft.Extensions.Caching.Redis实现Session共享的方法, ...
- .Net Core Web Api实践之中间件的使用(一)
前言:从2019年年中入坑.net core已半年有余,总体上来说虽然感觉坑多,但是用起来还是比较香的.本来我是不怎么喜欢写这类实践分享或填坑记录的博客的,因为初步实践坑多,文章肯定也会有各种错误,跟 ...
- ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)
GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...
- ASP.NET Core Web API
1.简单介绍 ASP.NET Core Web API 是 ASP.NET Core MVC 的一个功能.ASP.NET Core MVC 包含了对 Web API 的支持.可以构建多种客户端的 HT ...
- .net core web api + Autofac + EFCore 个人实践
1.背景 去年时候,写过一篇<Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统>,采用Asp.net Web API + Element-UI.当时主要是为了 ...
- ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理
在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行代码就展示了一个基本工作原理.然而,要将这样的解决方案运用到实际生产环境,还有很 ...
- 使用 ASP.NET Core MVC 创建 Web API(二)
使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 六.添加数据库上下文 数据库上下文是使用Entity Framewor ...
随机推荐
- 因为 Java 和 Php 在获取客户端 cookie 方式不同引发的 bug
遇到个 Java 和 Php 在获取客户端 cookie 方式不同导致跨系统的问题.所以写了这篇博客梳理下相关知识. 实验 下面通过两个简单的实验,来看Java和Php在获取web请求中的cookie ...
- NLP突破性成果 BERT 模型详细解读 bert参数微调
https://zhuanlan.zhihu.com/p/46997268 NLP突破性成果 BERT 模型详细解读 章鱼小丸子 不懂算法的产品经理不是好的程序员 关注她 82 人赞了该文章 Goo ...
- 阿里云ECS服务器活动99元一年,最高可买三年
这几天阿里云 99一年.279三年的服务器活动如火如荼,和之前腾讯三年的服务器非常类似,非常低的价格换取非常高的价值,当然,通常情况下便宜没好货的,想要玩一下的老铁可以进阿里云去看看,阿里云270三年 ...
- Codeforces 1100F(离线 or 在线)
传送门 •参考资料 [1]:在线线性基 [2]:离线线性基 [3]:离线线性基 •题意 给你 n 个数,m 次询问: 每次询问给定一个区间 $l,r$,求 $a_{l \cdots r}$ 异或的最大 ...
- SELECT command denied to user 'username'@'ip' for table 'user'错误处理
错误信息 使用RDS for MySQL,程序执行查询SQL时报错如下: SELECT command denied to user 'username'@'ip' for table 'user' ...
- 2018-8-10-win10-uwp-获取文件夹出错
title author date CreateTime categories win10 uwp 获取文件夹出错 lindexi 2018-08-10 19:16:50 +0800 2018-2-1 ...
- tensorflow在文本处理中的使用——Word2Vec预测
代码来源于:tensorflow机器学习实战指南(曾益强 译,2017年9月)——第七章:自然语言处理 代码地址:https://github.com/nfmcclure/tensorflow-coo ...
- H3C 三种生成树协议特性的比较
- H3C命令调试debugging--用户视图
<H3C>terminal debugging //使用debugging必须使用的命令--打开调试信 息的屏幕输出开关 <H3C>display debugging ...
- [数论] hdu 5974 A Simple Math Problem (数论gcd)
传送门 •题意 一直整数$a,b$,有 $\left\{\begin{matrix}x+y=a\\ LCM(x*y)=b \end{matrix}\right.$ 求$x,y$ •思路 解题重点:若$ ...