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>