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)
<!--配置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>
protected void Application_Start(object sender, EventArgs e) { //log4net初始化 //程序启动加入,在Web.config log4net:RollingLogFileAppender:file对应的日志目录或日志文件 log4net.Config.XmlConfigurator.Configure(); }五 读取写入缓存的类
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; } } }六 缓存与数据库
/// <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; } }七 dataSet转json
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; }八 WebService调用及返回Json数据
[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 + ")"); } }