nginx 分布式的使用
cmdWin7停nginx默认80端口被System占用,造成nginx启动报错的解决方案
www.MyException.Cn 网友分享于:2013-10-23 浏览:215次
Win7下nginx默认80端口被System占用,造成nginx启动报错的解决方案
问题:
在win7 32位旗舰版下,启动1.0.8版本nginx,显示如下错误:[plain]2012/04/02 13:55:59 [emerg] 7864#2376: bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)
解决方案:
在cmd窗口运行如下命令:netstat -aon | findstr :80
看到80端口果真被占用。发现占用的pid是4,名字是System。怎么禁用呢?
1、打开注册表编辑器:regedit
2、 找到HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/HTTP
3、 把REG_DWORD类型的项Start,将其改为0
4、重启系统,System进程不会占用80端口
如果还不行的话:
修改conf文件夹下的nginx.conf文件中的监听端口,原先为80,改为8088就OK了
server {
listen 8088;
一、简要介绍
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和 低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务,也可以支持作为 HTTP代理服务器对外进行服务。Nginx采用C进行编写,不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多。
作为邮件代理服务器:Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last. fm 描述了成功并且美妙的使用经验。
Nginx 是一个安装非常的简单,配置文件非常简洁(还能够支持perl语法),Bugs非常少的服务器:Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够不间断服务的情况下进行软件版本的升级。
(更多介绍参照百科,更多使用参照GOOGLE,广而告之)
二、下载安装
我们使用nginx 1.0.4 for windows版本,下载解压后放到C:\nginx-1.0.4(官网这样要求的,不知道放其它盘有没有问题)
运行cmd.exe到
有错误啊,也不知道启动成功没有,去看看日志吧。
logs里有出现了两个日志文件access.log,error.log, 打开error.log开到下面提示
2011/06/16 15:23:55 [emerg] 7136#4040: bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)
2011/06/16 15:24:14 [emerg] 6336#7052: bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)
去nginx官网搜了一下原因:
1 - Is there any firewall activated (e.g. windows Firewall)?
2 - Is there any program using port 80 (e.g. Skype) ?
Before starting NGINX type in the prompt :
TELNET 127.0.0.1 80
(NOTE: there is a space between the 80)
If it is successfull then there a program using the port.
3 - Have you tried to configure another port? If so, same error happens?
3个原因:
1.防火墙打开了(确实我的WIN7 windows Firewall打开了,但是关了后还是不能启动nginx)
2.80端口被占用了(确实有个默认的站点用的80端口,关闭了后再启动nginx正常了,80后为Nginx默认的配置)
怎么看出来的正常的,看一下logs下面是不是多了一个nginx.pid文件,cmd窗口了输入
C:\nginx-1.0.4>tasklist /fi "imagename eq nginx.exe"
结果如下:
这时说明已经启成功了,有两个进程。按照官方的解释,nginx是守护进程,其中一个是一直处理事件等待中,当有事件被触发时,就启动另外一个进程处理相关请求。
访问成功后可以logs下的access.log看到访问站点的request信息
View Code
如果没有成功可以再查看logs下的error.log原因,以下为其它操作命令
nginx -s stop |
quick exit |
nginx -s quit |
graceful quit |
nginx -s reload |
changing configuration, starting a new worker, quitting an old worker gracefully |
nginx -s reopen |
reopening log files |
官网提供了详细的windows usage 安装说明,网上大部分写的都很乱。我第一次参照网上其它人没成功过-_-|||,发现官网有安装说明照着操作一遍成功了,所以建议大家以后多看官网说明以及源码,可以少走很多弯路。
三、配置测试
第二环节我们使用了默认的nginx.conf 。Nginx的配置文件都存于目录conf文件下,其中nginx.conf是它的主配置文件。
以下为我加上注释并配置的新的虚拟server
View Code
#号为注释内容,我们在cmd下运行nginx
启动成功,出错的话,可以查询日志(日志路径是配置文件指定的,你可以修改存到其它位置)
一、实战
写一个web项目 发布到IIS上,index.aspx (在IIS上部署两个项目 端口号:8082 、9000)
修改配置文件:
C:\nginx-1.10.0\conf\nginx.conf
配置一个集群:server前面不能有空格,该文件最好不要用记事本打开,否则会自动加上Dom头。导致报错
下面这个文件,执行运行可以启动关闭或者重启nginx
主要内容:@echo off
rem 当前bat的作用
echo ==================begin========================
cls
SET NGINX_PATH=%~d0
SET NGINX_DIR=%~dp0
color 0a
TITLE Nginx 管理程序 Power By Ants (http://leleroyn.cnblogs.com)
CLS
ECHO.
ECHO. * * Nginx 管理程序 Power By Ants (http://leleroyn.cnblogs.com) *
ECHO.
ECHO.
:MENU
ECHO. * nginx 进程list *
tasklist|findstr /i "nginx.exe"
ECHO.
ECHO. [1] 启动Nginx
ECHO. [2] 关闭Nginx
ECHO. [3] 重启Nginx
ECHO. [4] 退 出
ECHO.
ECHO.请输入选择项目的序号:
set /p ID=
IF "%id%"=="1" GOTO start
IF "%id%"=="2" GOTO stop
IF "%id%"=="3" GOTO restart
IF "%id%"=="4" EXIT
PAUSE
:start
call :startNginx
GOTO MENU
:stop
call :shutdownNginx
GOTO MENU
:restart
call :shutdownNginx
call :startNginx
GOTO MENU
:shutdownNginx
ECHO.
ECHO.关闭Nginx......
taskkill /F /IM nginx.exe > nul
ECHO.OK,关闭所有nginx 进程
goto :eof
:startNginx
ECHO.
ECHO.启动Nginx......
IF NOT EXIST "%NGINX_DIR%nginx.exe" ECHO "%NGINX_DIR%nginx.exe"不存在
%NGINX_PATH%
cd "%NGINX_DIR%"
IF EXIST "%NGINX_DIR%nginx.exe" (
echo "start '' nginx.exe"
start "" nginx.exe
)
ECHO.OK
goto :eof
最后直接在浏览器输入:http://127.0.0.1:8088/index.aspx 实现了分布式
Nginx.conf 配置里面默认端口号:80 可自行修改
负载的服务器配置不一样,有的高有的低可不可以让配置高的服务器处理请求多一些
- 这里讲一下,负载均衡有好几种算法 轮转法,散列法, 最少连接法,最低缺失法,最快响应法,加权法。我们这里可以使用加权法来分配请求。
upstream Jq_one{
server 127.0.0.1:8082 weight=4;
server 127.0.0.1:9000 weight=1;
}
通过weight设置每台服务器分配请求站的权重,值越高分配的越多。
由于请求是经过nginx转发过来的,可以在代码里面获取到用户请求的实际ip地址吗?
- 答案是肯定的,在localtion节点设置如下请求头信息
#设置主机头和客户端真实地址,以便服务器获取客户端真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
代码里面通过Request.Headers["X-Real-IP"],就能获取到真实ip
二、配置MVC项目
刚安装的版本适合 aspx页面,要想使用mvc,还需要修改一下配置:
1.
添加:
fastcgi_pass 127.0.0.1:8080; #fastcgi的监听端口
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #由于我把nginx放到C盘的根目录,如果放到其他地方的话 目录#要写对
2.更改另外一个配置文件:
添加
fastcgi_param PATH_INFO "";
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
三、使用Redis实现Session共享
1.redis基本配置
1.1配置
<section
name="RedisConfig" type="Custom_RedisSessionStateStore.RedisConfigInfo,Custom_RedisSessionStateStore
"/>
<RedisConfig WriteServerList="127.0.0.1:6379" ReadServerList="127.0.0.1:6379" MaxWritePoolSize="60" MaxReadPoolSize="60" AutoStart="true" LocalCacheTime="180" RecordeLog="false">
</RedisConfig>
1.2 基本代码
RedisConfigInfo 类:读取以上配置信息
namespace Custom_RedisSessionStateStore
{
public class RedisConfigInfo : ConfigurationSection
{
/// <summary>
/// 可写的Redis链接地址
/// </summary>
[ConfigurationProperty("WriteServerList", IsRequired = false)]
public string WriteServerList
{
get
{
return (string)base["WriteServerList"];
}
set
{
base["WriteServerList"] = value;
}
}
/// <summary>
/// 可读的Redis链接地址
/// </summary>
[ConfigurationProperty("ReadServerList", IsRequired = false)]
public string ReadServerList
{
get
{
return (string)base["ReadServerList"];
}
set
{
base["ReadServerList"] = value;
}
}
/// <summary>
/// 最大写链接数
/// </summary>
[ConfigurationProperty("MaxWritePoolSize", IsRequired = false, DefaultValue = 5)]
public int MaxWritePoolSize
{
get
{
int _maxWritePoolSize = (int)base["MaxWritePoolSize"];
return _maxWritePoolSize > 0 ? _maxWritePoolSize : 5;
}
set
{
base["MaxWritePoolSize"] = value;
}
}
/// <summary>
/// 最大读链接数
/// </summary>
[ConfigurationProperty("MaxReadPoolSize", IsRequired = false, DefaultValue = 5)]
public int MaxReadPoolSize
{
get
{
int _maxReadPoolSize = (int)base["MaxReadPoolSize"];
return _maxReadPoolSize > 0 ? _maxReadPoolSize : 5;
}
set
{
base["MaxReadPoolSize"] = value;
}
}
/// <summary>
/// 自动重启
/// </summary>
[ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)]
public bool AutoStart
{
get
{
return (bool)base["AutoStart"];
}
set
{
base["AutoStart"] = value;
}
}
/// <summary>
/// 本地缓存到期时间,单位:秒
/// </summary>
[ConfigurationProperty("LocalCacheTime", IsRequired = false, DefaultValue = 36000)]
public int LocalCacheTime
{
get
{
return (int)base["LocalCacheTime"];
}
set
{
base["LocalCacheTime"] = value;
}
}
/// <summary>
/// 是否记录日志,该设置仅用于排查redis运行时出现的问题,如redis工作正常,请关闭该项
/// </summary>
[ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)]
public bool RecordeLog
{
get
{
return (bool)base["RecordeLog"];
}
set
{
base["RecordeLog"] = value;
}
}
public static RedisConfigInfo GetConfigInfo()
{
RedisConfigInfo section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
return section;
}
public static RedisConfigInfo GetConfig(string sectionName)
{
RedisConfigInfo section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
if (section == null)
throw new ConfigurationErrorsException("Section " + sectionName + " is not found.");
return section;
}
}
}
RedisManager:redis操作类
public class RedisManager
{
private static RedisConfigInfo redisConfig = RedisConfigInfo.GetConfigInfo();
private static PooledRedisClientManager prcm;
static RedisManager()
{
CreateManager();
}
private static void CreateManager()
{
string[] writeServiceList = SplitString(redisConfig.WriteServerList, ",");
string[] readServiceList = SplitString(redisConfig.ReadServerList, ",");
prcm = new PooledRedisClientManager(readServiceList, writeServiceList, new RedisClientManagerConfig() { MaxWritePoolSize = redisConfig.MaxWritePoolSize, MaxReadPoolSize = redisConfig.MaxReadPoolSize, AutoStart = redisConfig.AutoStart });
}
public static IRedisClient GetClient()
{
if (prcm == null)
{
CreateManager();
}
return prcm.GetClient();
}
private static string[] SplitString(string strSource, string split)
{
return strSource.Split(split.ToArray());
}
#region -- Item --
/// <summary>
/// 设置单体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="t"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static bool Item_Set<T>(string key, T t)
{
try
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.Set<T>(key, t, new TimeSpan(1, 0, 0));
}
}
catch (Exception ex)
{
// LogInfo
}
return false;
}
/// <summary>
/// 设置单体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="t"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static bool Item_Set<T>(string key, T t, int timeout)
{
try
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.Set<T>(key, t, new TimeSpan(0, timeout, 0));
}
}
catch (Exception ex)
{
}
return false;
}
/// <summary>
/// 获取单体
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static T Item_Get<T>(string key) where T : class
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.Get<T>(key);
}
}
/// <summary>
/// 移除单体
/// </summary>
/// <param name="key"></param>
public static bool Item_Remove(string key)
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.Remove(key);
}
}
/// <summary>
/// 设置缓存过期
/// </summary>
/// <param name="key"></param>
public static bool Item_SetExpire(string key, int timeout)
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.ExpireEntryIn(key, new TimeSpan(0, timeout, 0));
}
}
#endregion
#region -- List --
public static void List_Add<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient =redis.As<T>();
redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
}
}
public static bool List_Remove<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient = redis.As<T>();
return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
}
}
public static void List_RemoveAll<T>(string key)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient = redis.As<T>();
redisTypedClient.Lists[key].RemoveAll();
}
}
public static int List_Count(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
return (int)redis.GetListCount(key);
}
}
public static List<T> List_GetRange<T>(string key, int start, int count)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
var c = redis.As<T>();
return c.Lists[key].GetRange(start, start + count - 1);
}
}
public static List<T> List_GetList<T>(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
var c = redis.As<T>();
return c.Lists[key].GetRange(0, c.Lists[key].Count);
}
}
public static List<T> List_GetList<T>(string key, int pageIndex, int pageSize)
{
int start = pageSize * (pageIndex - 1);
return List_GetRange<T>(key, start, pageSize);
}
/// <summary>
/// 设置缓存过期
/// </summary>
/// <param name="key"></param>
/// <param name="datetime"></param>
public static void List_SetExpire(string key, DateTime datetime)
{
using (IRedisClient redis = prcm.GetClient())
{
redis.ExpireEntryAt(key, datetime);
}
}
#endregion
#region -- Set --
public static void Set_Add<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient = redis.As<T>();
redisTypedClient.Sets[key].Add(t);
}
}
public static bool Set_Contains<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient = redis.As<T>();
return redisTypedClient.Sets[key].Contains(t);
}
}
public static bool Set_Remove<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
var redisTypedClient = redis.As<T>();
return redisTypedClient.Sets[key].Remove(t);
}
}
#endregion
#region -- Hash --
/// <summary>
/// 判断某个数据是否已经被缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="dataKey"></param>
/// <returns></returns>
public static bool Hash_Exist<T>(string key, string dataKey)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
return redis.HashContainsEntry(key, dataKey);
}
}
public static int Hash_GetCount(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
return (int)redis.GetHashCount(key);
}
}
/// <summary>
/// 存储数据到hash表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="dataKey"></param>
/// <returns></returns>
public static bool Hash_Set<T>(string key, string dataKey, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
return redis.SetEntryInHash(key, dataKey, value);
}
}
/// <summary>
/// 移除hash中的某值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="dataKey"></param>
/// <returns></returns>
public static bool Hash_Remove(string key, string dataKey)
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.RemoveEntryFromHash(key, dataKey);
}
}
/// <summary>
/// 移除整个hash
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="dataKey"></param>
/// <returns></returns>
public static bool Hash_Remove(string key)
{
using (IRedisClient redis = prcm.GetClient())
{
return redis.Remove(key);
}
}
/// <summary>
/// 从hash表获取数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="dataKey"></param>
/// <returns></returns>
public static T Hash_Get<T>(string key, string dataKey)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
string value = redis.GetValueFromHash(key, dataKey);
return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(value);
}
}
/// <summary>
/// 获取整个hash的数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static List<T> Hash_GetAll<T>(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
var list = redis.GetHashValues(key);
if (list != null && list.Count > 0)
{
List<T> result = new List<T>();
foreach (var item in list)
{
var value = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
result.Add(value);
}
return result;
}
return null;
}
}
/// <summary>
/// 设置缓存过期
/// </summary>
/// <param name="key"></param>
/// <param name="datetime"></param>
public static void Hash_SetExpire(string key, DateTime datetime)
{
using (IRedisClient redis = prcm.GetClient())
{
redis.ExpireEntryAt(key, datetime);
}
}
#endregion
#region -- SortedSet --
/// <summary>
/// 添加数据到 SortedSet
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="t"></param>
/// <param name="score"></param>
public static bool SortedSet_Add<T>(string key, T t, double score)
{
using (IRedisClient redis = prcm.GetClient())
{
string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
return redis.AddItemToSortedSet(key, value, score);
}
}
/// <summary>
/// 移除数据从SortedSet
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="t"></param>
/// <returns></returns>
public static bool SortedSet_Remove<T>(string key, T t)
{
using (IRedisClient redis = prcm.GetClient())
{
string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
return redis.RemoveItemFromSortedSet(key, value);
}
}
/// <summary>
/// 修剪SortedSet
/// </summary>
/// <param name="key"></param>
/// <param name="size">保留的条数</param>
/// <returns></returns>
public static int SortedSet_Trim(string key, int size)
{
using (IRedisClient redis = prcm.GetClient())
{
return (int)redis.RemoveRangeFromSortedSet(key, size, 9999999);
}
}
/// <summary>
/// 获取SortedSet的长度
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static int SortedSet_Count(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
return (int)redis.GetSortedSetCount(key);
}
}
/// <summary>
/// 获取SortedSet的分页数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public static List<T> SortedSet_GetList<T>(string key, int pageIndex, int pageSize)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
var list = redis.GetRangeFromSortedSet(key, (pageIndex - 1) * pageSize, pageIndex * pageSize - 1);
if (list != null && list.Count > 0)
{
List<T> result = new List<T>();
foreach (var item in list)
{
var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
result.Add(data);
}
return result;
}
}
return null;
}
/// <summary>
/// 获取SortedSet的全部数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public static List<T> SortedSet_GetListALL<T>(string key)
{
using (IRedisClient redis = prcm.GetReadOnlyClient())
{
var list = redis.GetRangeFromSortedSet(key, 0, 9999999);
if (list != null && list.Count > 0)
{
List<T> result = new List<T>();
foreach (var item in list)
{
var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
result.Add(data);
}
return result;
}
}
return null;
}
/// <summary>
/// 设置缓存过期
/// </summary>
/// <param name="key"></param>
/// <param name="datetime"></param>
public static void SortedSet_SetExpire(string key, DateTime datetime)
{
using (IRedisClient redis = prcm.GetClient())
{
redis.ExpireEntryAt(key, datetime);
}
}
#endregion
}
2.mode="InProc"
这里配置不需要改,默认的就行
设置Cookies
public static string GetSessionID(HttpRequestBase request, HttpResponseBase response, bool IsReadOnly, int Timeout)
{
// Response.Cookies("MyCookie").Path = "/"
HttpCookie cookies = request.Cookies[SessionName];
if (cookies == null || string.IsNullOrEmpty(cookies.Value))
{
string newSessionID = Guid.NewGuid().ToString();
HttpCookie httpCookies = new HttpCookie(SessionName, newSessionID);
httpCookies.HttpOnly = IsReadOnly;
httpCookies.Path = "/";
httpCookies.Expires = DateTime.Now.AddMinutes(Timeout);
RedisManager.Hash_SetExpire(newSessionID, DateTime.Now.AddMinutes(Timeout));
response.AppendCookie(httpCookies);
return "Session_" + newSessionID;
}else
{
return "Session_" + cookies.Value;
}
3.mode="Custom"
3.1 RedisSessionStateStore类:
/// <summary>
/// 使用Cookie实现SessionStateStoreProviderBase
/// 注意:它只适合保存简单的基元类型数据。
/// </summary>
public class RedisSessionStateStore:SessionStateStoreProviderBase
{
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return CreateLegitStoreData(context, null, null, timeout);
}
internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
if (sessionItems == null)
sessionItems = new SessionStateItemCollection();
if (staticObjects == null && context != null)
staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
return new SessionStateStoreData(sessionItems, staticObjects, timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
RedisSessionState state = new RedisSessionState(null, null, timeout);
RedisManager.Item_Set<string>(id, state.ToJson(), timeout);
}
private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
locked = false;
lockId = null;
lockAge = TimeSpan.Zero;
actionFlags = SessionStateActions.None;
RedisSessionState state = RedisSessionState.FromJson(RedisManager.Item_Get<string>(id));
if (state == null)
{
return null;
}
RedisManager.Item_SetExpire(id, state._timeout);
return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout);
}
public override void Dispose()
{
}
public override void EndRequest(HttpContext context)
{
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags);
}
public override void InitializeRequest(HttpContext context)
{
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
RedisManager.Item_Remove(id);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
ISessionStateItemCollection sessionItems = null;
HttpStaticObjectsCollection staticObjects = null;
if (item.Items.Count > 0)
sessionItems = item.Items;
if (!item.StaticObjects.NeverAccessed)
staticObjects = item.StaticObjects;
RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout);
RedisManager.Item_Set<string>(id, state2.ToJson(), item.Timeout);
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return true;
}
}
internal sealed class SessionStateItem
{
public Dictionary<string, object> Dict;
public int Timeout;
}
internal sealed class RedisSessionState
{
internal ISessionStateItemCollection _sessionItems;
internal HttpStaticObjectsCollection _staticObjects;
internal int _timeout;
internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
this.Copy(sessionItems, staticObjects, timeout);
}
internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
this._sessionItems = sessionItems;
this._staticObjects = staticObjects;
this._timeout = timeout;
}
public string ToJson()
{
// 这里忽略_staticObjects这个成员。
if (_sessionItems == null || _sessionItems.Count == 0)
{
return null;
}
Dictionary<string, object> dict = new Dictionary<string, object>(_sessionItems.Count);
string key;
NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys;
for (int i = 0; i < keys.Count; i++)
{
key = keys[i];
dict.Add(key, _sessionItems[key]);
}
SessionStateItem item = new SessionStateItem { Dict = dict, Timeout = this._timeout };
return JsonConvert.SerializeObject(item);
}
public static RedisSessionState FromJson(string json)
{
if (string.IsNullOrEmpty(json))
{
return null;
}
try
{
SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json);
SessionStateItemCollection collections = new SessionStateItemCollection();
foreach (KeyValuePair<string, object> kvp in item.Dict)
{
collections[kvp.Key] = kvp.Value;
}
return new RedisSessionState(collections, null, item.Timeout);
}
catch
{
return null;
}
}
}
3.2 配置
<sessionState mode="Custom" customProvider="RedisSessionStateStore">
<providers>
<add name="RedisSessionStateStore" type="Custom_RedisSessionStateStore.RedisSessionStateStore"/>
</providers>
</sessionState>