|
要点
memcached, Enyim, log4net, Newtonsoft.Json
一 环境
注意Enyim,log4net,memcached的版本,如果与下面不一至,调试运行中有可能出现问题
1.memcached客户端
Enyim.Caching.dll v2.12.0.0
Enyim.Caching.Log4NetAdapter.dll v2.12.0.0
log4net.dll v1.2.10.0
2.memcached服务端
memcached-win32 v1.4.4-14
3.数据输出及提供
数据输出格式:json
数据提供:WebService
4.dataSet转json
组件:Newtonsoft.Json.dll v4.0.8.14612
5.开发工具
visual studio 2010
6.dotNet
开发版本:.net v3.5
运行版本:.net v2.0.50727
二 memcached安装启动
1.安装
memcached.exe -d install
服务启动后, memcached 默认使用 64M 内存和 11211 端口作为服务器参数。
如果你希望调整参数,请参考: memcached.exe -h
2.启动
memcached.exe -m 512 -p 33000 -d start
-d为守护进程启动
-m为指定内存大小
-p指定端口,默认端口11211
3.测试memcached
d:\>telnet localhost 11211
add firstKey 0 0 15
Hello Memcached
STORED
get firstKey
VALUE firstKey 0 15
Hello Memcached
END
quit
三 memcached及log4net配置(Web.config)
[html] viewplaincopy
- <!--配置memcached服务器及log4net日志-->
- <configuration>
- <configSections>
- <!-- ... 其它配置 -->
-
- <!--log4net日志配置-->
- <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
- <!--缓存客户端配置-->
- <sectionGroup name="enyim.com">
- <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
- <section name="log" type="Enyim.Caching.Configuration.LoggerSection, Enyim.Caching"/>
- </sectionGroup>
- <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
- </configSections>
- <!--缓存客户端配置-->
- <enyim.com>
- <log factory="Enyim.Caching.Log4NetFactory, Enyim.Caching.Log4NetAdapter"/>
- <memcached>
- <servers>
- <add address="192.168.0.45" port="11211"/>
- </servers>
- <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
- </memcached>
- </enyim.com>
- <memcached>
- <servers>
- <add address="192.168.0.45" port="11211"/>
- </servers>
- <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
- </memcached>
- <!--log4net日志配置-->
- <!--Basic log4net config. Don't forget to call log4net.Config.XmlConfigurator.Configure(); at the start of your app.-->
- <log4net>
- <root>
- <level value="ALL"/>
- <appender-ref ref="RollingLogFileAppender"/>
- <appender-ref ref="ConsoleAppender"/>
- <appender-ref ref="TraceAppender"/>
- </root>
- <logger name="Enyim.Caching.Memcached.DefaultNodeLocator">
- <level value="Debug"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.PooledSocket">
- <level value="Info"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.Protocol">
- <level value="Info"/>
- </logger>
- <logger name="Membase.VBucketAwareOperationFactory">
- <level value="Info"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.MemcachedNode">
- <level value="Info"/>
- </logger>
- <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
- <param name="File" value="LogFiles/"/>
- <param name="AppendToFile" value="true"/>
- <param name="MaxSizeRollBackups" value="10"/>
- <param name="StaticLogFileName" value="false"/>
- <param name="DatePattern" value="yyyy-MM-dd".txt""/>
- <param name="RollingStyle" value="Date"/>
- <layout type="log4net.Layout.PatternLayout">
- <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%thread] %-5level %c %L %F - %message%newline"/>
- </layout>
- <footer value="by anyx"/>
- </appender>
- <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
- <layout type="log4net.Layout.PatternLayout,log4net">
- <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
- </layout>
- </appender>
- <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
- <layout type="log4net.Layout.PatternLayout,log4net">
- <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
- </layout>
- </appender>
- </log4net>
- <!-- 缓存期限 -->
- <appSettings>
- <add key="cachingTime" value="120"/>
- </appSettings>
- <!-- 数据库连接 -->
- <connectionStrings>
- <add name="dbConnStr" connectionString="Data Source=APPCtl;User ID=appuser;Password=appuser123;Integrated Security = false" providerName="System.Data.OracleClient"/>
- </connectionStrings>
- <system.web>
- <!-- 用于跨域调用 -->
- <webServices>
- <protocols>
- <add name="HttpGet"/>
- <add name="HttpPost"/>
- </protocols>
- </webServices>
- <!-- ... 其它配置 -->
- </system.web>
- <!-- ... 其它配置 -->
- </configuration>
[html] viewplaincopy
- <span style="font-size:14px;"><!--配置memcached服务器及log4net日志-->
- <configuration>
- <configSections>
- <!-- ... 其它配置 -->
-
- <!--log4net日志配置-->
- <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
- <!--缓存客户端配置-->
- <sectionGroup name="enyim.com">
- <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
- <section name="log" type="Enyim.Caching.Configuration.LoggerSection, Enyim.Caching"/>
- </sectionGroup>
- <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
- </configSections>
- <!--缓存客户端配置-->
- <enyim.com>
- <log factory="Enyim.Caching.Log4NetFactory, Enyim.Caching.Log4NetAdapter"/>
- <memcached>
- <servers>
- <add address="192.168.0.45" port="11211"/>
- </servers>
- <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
- </memcached>
- </enyim.com>
- <memcached>
- <servers>
- <add address="192.168.0.45" port="11211"/>
- </servers>
- <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
- </memcached>
- <!--log4net日志配置-->
- <!--Basic log4net config. Don't forget to call log4net.Config.XmlConfigurator.Configure(); at the start of your app.-->
- <log4net>
- <root>
- <level value="ALL"/>
- <appender-ref ref="RollingLogFileAppender"/>
- <appender-ref ref="ConsoleAppender"/>
- <appender-ref ref="TraceAppender"/>
- </root>
- <logger name="Enyim.Caching.Memcached.DefaultNodeLocator">
- <level value="Debug"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.PooledSocket">
- <level value="Info"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.Protocol">
- <level value="Info"/>
- </logger>
- <logger name="Membase.VBucketAwareOperationFactory">
- <level value="Info"/>
- </logger>
- <logger name="Enyim.Caching.Memcached.MemcachedNode">
- <level value="Info"/>
- </logger>
- <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
- <param name="File" value="LogFiles/"/>
- <param name="AppendToFile" value="true"/>
- <param name="MaxSizeRollBackups" value="10"/>
- <param name="StaticLogFileName" value="false"/>
- <param name="DatePattern" value="yyyy-MM-dd".txt""/>
- <param name="RollingStyle" value="Date"/>
- <layout type="log4net.Layout.PatternLayout">
- <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%thread] %-5level %c %L %F - %message%newline"/>
- </layout>
- <footer value="by anyx"/>
- </appender>
- <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
- <layout type="log4net.Layout.PatternLayout,log4net">
- <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
- </layout>
- </appender>
- <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
- <layout type="log4net.Layout.PatternLayout,log4net">
- <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
- </layout>
- </appender>
- </log4net>
- <!-- 缓存期限 -->
- <appSettings>
- <add key="cachingTime" value="120"/>
- </appSettings>
- <!-- 数据库连接 -->
- <connectionStrings>
- <add name="dbConnStr" connectionString="Data Source=APPCtl;User ID=appuser;Password=appuser123;Integrated Security = false" providerName="System.Data.OracleClient"/>
- </connectionStrings>
- <system.web>
- <!-- 用于跨域调用 -->
- <webServices>
- <protocols>
- <add name="HttpGet"/>
- <add name="HttpPost"/>
- </protocols>
- </webServices>
- <!-- ... 其它配置 -->
- </system.web>
- <!-- ... 其它配置 -->
- </configuration></span>
四 log4net初始化
初始化Web.config中配置的log4net
在Global.asax下:
[csharp] viewplaincopy
- protected void Application_Start(object sender, EventArgs e)
- {
- //log4net初始化
- //程序启动加入,在Web.config log4net:RollingLogFileAppender:file对应的日志目录或日志文件
- log4net.Config.XmlConfigurator.Configure();
- }
[csharp] viewplaincopy
- <span style="font-size:14px;">protected void Application_Start(object sender, EventArgs e)
- {
- //log4net初始化
- //程序启动加入,在Web.config log4net:RollingLogFileAppender:file对应的日志目录或日志文件
- log4net.Config.XmlConfigurator.Configure();
- }</span>
五 读取写入缓存的类
注意,以下读取写入Memcached是基于memcached v1.4以后的版本
建一个类,用于读取和写入Memcached.
[csharp] viewplaincopy
- public class CachedService
- {
- private static MemcachedClient mc = new MemcachedClient();
- /// <summary>
- /// 从缓存服务器取出数据
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static object getObjectFromCached(string key)
- {
- //...
- Object obj = null;
- IGetOperationResult result = mc.ExecuteGet(key);
- if (result.HasValue)
- {
- obj = result.Value;
- }
- return obj;
- //...
- }
-
- /// <summary>
- /// 存入数据到缓存服务器
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static bool setObjectToCached(string key, object obj)
- {
- //读取Web.config配置中的缓存时间
- double cachintTime = 0;
- string ct = System.Configuration.ConfigurationManager.AppSettings["cachingTime"];
- if (!string.IsNullOrEmpty(ct))
- {
- cachintTime = Convert.ToDouble(ct);
- }
- //缓存数据
- IStoreOperationResult result = mc.ExecuteStore(StoreMode.Set, key, obj, DateTime.Now.AddMinutes(cachintTime));
- if (result.Success)
- {
- return true;
- }
- else
- {
- string me = result.Message;
- int code = Convert.ToInt32(result.StatusCode);
-
- return false;
- }
- }
- }
[csharp] viewplaincopy
- <span style="font-size:14px;">public class CachedService
- {
- private static MemcachedClient mc = new MemcachedClient();
- /// <summary>
- /// 从缓存服务器取出数据
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static object getObjectFromCached(string key)
- {
- //...
- Object obj = null;
- IGetOperationResult result = mc.ExecuteGet(key);
- if (result.HasValue)
- {
- obj = result.Value;
- }
- return obj;
- //...
- }
-
- /// <summary>
- /// 存入数据到缓存服务器
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static bool setObjectToCached(string key, object obj)
- {
- //读取Web.config配置中的缓存时间
- double cachintTime = 0;
- string ct = System.Configuration.ConfigurationManager.AppSettings["cachingTime"];
- if (!string.IsNullOrEmpty(ct))
- {
- cachintTime = Convert.ToDouble(ct);
- }
- //缓存数据
- IStoreOperationResult result = mc.ExecuteStore(StoreMode.Set, key, obj, DateTime.Now.AddMinutes(cachintTime));
- if (result.Success)
- {
- return true;
- }
- else
- {
- string me = result.Message;
- int code = Convert.ToInt32(result.StatusCode);
-
- return false;
- }
- }
- }</span>
六 缓存与数据库
取数据首先查看Memcached缓存服务器是否有对应键的数据对象,如果有,就直接取出,如果没有,就从数据库取出,再按相应键存入Memcached.
[csharp] viewplaincopy
- /// <summary>
- /// 每日龙虎榜:最近交易日:缺省数据:分页(缓存服务器)
- /// </summary>
- /// <returns>返回Json格式字符串</returns>
- public class SomeClass
- {
- public string getSomeData(int start,int limit,string sf,string sr)
- {
- if (string.IsNullOrEmpty(sf) || string.IsNullOrEmpty(sr))
- {
- //某些参数为空,返回
- return "{\"total\":0,\"rows\":[]}"; ;
- }
-
- string json = "";
-
- //缓存服务器唯一标识,命名很重要
- //在这里我采用的是查询条件作为缓存标识
- string key = "edaylhb:" + start + ":" + limit + ":" + sf + ":" + sr;
-
- //从缓存服务器中取对应key的数据
- Object obj = CachedService.getObjectFromCached(key);
-
- if (obj != null)
- {
- //缓存服务器中有数据
- json = (string)obj;
- }
- else
- {
- //缓存服务器中无数据,去数据库取,再保存到缓存服务器
-
- //查询数据库,返回dataset ds
-
- //...各种sql查询
-
- try{
- string ds2Str = "";
-
- //如果ds不为空,转换为Json格式
- ds2Str = DbUtil.dataSet2Json(ds);
- ds.Dispose();
-
-
- //拼接成Json格式
- if (ds.Tables[0].Rows.Count == 0)
- {
- json = "{\"total\":0,\"rows\":[]}";
- }
- else
- {
- json = "{\"total\":" + ds.Tables[0].Rows.Count + ",\"rows\":" + ds2Str + "}";
- }
- //保存数据到缓存服务器
- CachedService.setObjectToCached(key, json);
- }
- catch (Exception ex)
- {
- //异常记录到日志
- Log4netService.log4netFatal(MethodBase.GetCurrentMethod().DeclaringType, ex);
- throw ex;
- }
- }
- return json;
- }
- }
[csharp] viewplaincopy
- <span style="font-size:14px;"> /// <summary>
- /// 每日龙虎榜:最近交易日:缺省数据:分页(缓存服务器)
- /// </summary>
- /// <returns>返回Json格式字符串</returns>
- public class SomeClass
- {
- public string getSomeData(int start,int limit,string sf,string sr)
- {
- if (string.IsNullOrEmpty(sf) || string.IsNullOrEmpty(sr))
- {
- //某些参数为空,返回
- return "{\"total\":0,\"rows\":[]}"; ;
- }
-
- string json = "";
-
- //缓存服务器唯一标识,命名很重要
- //在这里我采用的是查询条件作为缓存标识
- string key = "edaylhb:" + start + ":" + limit + ":" + sf + ":" + sr;
-
- //从缓存服务器中取对应key的数据
- Object obj = CachedService.getObjectFromCached(key);
-
- if (obj != null)
- {
- //缓存服务器中有数据
- json = (string)obj;
- }
- else
- {
- //缓存服务器中无数据,去数据库取,再保存到缓存服务器
-
- //查询数据库,返回dataset ds
-
- //...各种sql查询
-
- try{
- string ds2Str = "";
-
- //如果ds不为空,转换为Json格式
- ds2Str = DbUtil.dataSet2Json(ds);
- ds.Dispose();
-
-
- //拼接成Json格式
- if (ds.Tables[0].Rows.Count == 0)
- {
- json = "{\"total\":0,\"rows\":[]}";
- }
- else
- {
- json = "{\"total\":" + ds.Tables[0].Rows.Count + ",\"rows\":" + ds2Str + "}";
- }
- //保存数据到缓存服务器
- CachedService.setObjectToCached(key, json);
- }
- catch (Exception ex)
- {
- //异常记录到日志
- Log4netService.log4netFatal(MethodBase.GetCurrentMethod().DeclaringType, ex);
- throw ex;
- }
- }
- return json;
- }
- }</span>
七 dataSet转json
[csharp] viewplaincopy
- public static string dataSet2Json(DataSet ds)
- {
- string jsonStr = null;
-
- //Newtonsoft.Json在转换日期的时候,会出现格式和时区(差8小时)差别 Trade_Status_Name
- //如果不作如下格式转换,会出现形如Date(1335247957000+0800)/的日期
- IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
- //这里使用自定义日期格式,如果不使用的话,默认是ISO8601格式
- timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
- jsonStr = JsonConvert.SerializeObject(ds.Tables[0], Formatting.Indented, timeConverter);
- //jsonStr = "[{Stk_Code:'601398',Stk_name:'工商银行'},{Stk_Code:'500999',Stk_name:'农业银行'}]";
-
- return jsonStr;
- }
[csharp] viewplaincopy
- <span style="font-size:14px;">public static string dataSet2Json(DataSet ds)
- {
- string jsonStr = null;
-
- //Newtonsoft.Json在转换日期的时候,会出现格式和时区(差8小时)差别 Trade_Status_Name
- //如果不作如下格式转换,会出现形如Date(1335247957000+0800)/的日期
- IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
- //这里使用自定义日期格式,如果不使用的话,默认是ISO8601格式
- timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
- jsonStr = JsonConvert.SerializeObject(ds.Tables[0], Formatting.Indented, timeConverter);
- //jsonStr = "[{Stk_Code:'601398',Stk_name:'工商银行'},{Stk_Code:'500999',Stk_name:'农业银行'}]";
-
- return jsonStr;
- }</span>
八 WebService调用及返回Json数据
[csharp] viewplaincopy
- [System.Web.Script.Services.ScriptService]
- public class TestWebService : System.Web.Services.WebService
- {
- /// <summary>
- /// </summary>
- [WebMethod]
- public void getTestData()
- {
- string cb = Context.Request["callback"]; //跨域服务器发送jsonp的参数key
- int start = Convert.ToInt32(string.IsNullOrEmpty(Context.Request["start"]) ? "1" : Context.Request["start"]); //从第几页开始:默认第一次从1开始,next_start=start+limit
- int limit = Convert.ToInt32(string.IsNullOrEmpty(Context.Request["limit"]) ? "20" : Context.Request["limit"]); //每次取的条数(步进):默认每页20条
- string sf = string.IsNullOrEmpty(Context.Request["sf"]) ? "se_code" : Context.Request["sf"]; //sortField 排序字段,默认:se_code
- string sr = string.IsNullOrEmpty(Context.Request["sr"]) ? "asc" : Context.Request["sr"]; //sortRule 排序规则,默认:asc
-
- SomeClass svr = new SomeClass();
- string json = svr.getSomeData(start, limit, sf, sr);
-
- Context.Response.ContentType = "text/plain; charset=utf-8";
- //Context.Response.Write(cb + "({\"total\":30,\"rows\":[{\"ID\":1,\"NAME\":\"John\"},{\"ID\":2,\"NAME\":\"Mike\"}]})");
- Context.Response.Write(cb + "(" + json + ")");
- }
- }
http://blog.iyunv.com/meeweed/article/details/8665900 |
|