using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Runtime.Serialization.Json; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Platform.Facilitys { public static class HttpHelper { static readonly HttpClient _client; static HttpHelper() { _client = new HttpClient(); } public static TOut PostSync<TIn, TOut>(ApiHost host, TIn postData) where TIn : class where TOut : class { var uri = new Uri(host.Domain); var url = new Uri(uri, host.ApiName); var response = _client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(postData),Encoding.UTF8,host.DataMimeType)).Result; response.EnsureSuccessStatusCode(); return response.Content.DesObj<TOut>(); } public static Task<TOut> PostAsync<TIn, TOut>(ApiHost host, TIn postData) where TIn : class where TOut : class { var uri = new Uri(host.Domain); var url = new Uri(uri, host.ApiName); return _client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(postData), Encoding.UTF8, host.DataMimeType)).GetResult<TOut>(); } public static Task<TOut> GetAsync<TOut>(ApiHost host) where TOut : class { var uri = new Uri(host.Domain); var url = new Uri(uri, host.ApiName); return _client.GetAsync(url).GetResult<TOut>(); } static Task<TOut> GetResult<TOut>(this Task<HttpResponseMessage> tsk) where TOut : class { return tsk.ContinueWith( res => { return res .Result .EnsureSuccessStatusCode() .Content .DesObj<TOut>(); }, TaskContinuationOptions.OnlyOnRanToCompletion); } static TOut DesObj<TOut>(this HttpContent content) where TOut : class { var strJson = content.ReadAsStringAsync().Result; if (!string.IsNullOrWhiteSpace(strJson)) { if (strJson.IndexOf("k__BackingField") > 0) { DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TOut)); using (var mStream = new MemoryStream(Encoding.Default.GetBytes(strJson))) { return ser.ReadObject(mStream) as TOut; } } else { return JsonConvert.DeserializeObject<TOut>(strJson); } } return default(TOut); } } /// <summary> /// WebApi配置 /// </summary> public class ApiHost { #region public ApiHost() { DataMimeType = "application/json"; } public ApiHost(string domain, string apiName, string inputQueryString, string dataMimeType) { Domain = domain; ApiName = apiName; InputQueryString = inputQueryString; DataMimeType = dataMimeType; } #endregion #region /// <summary> /// 主域名(比如http://api.rongzi.com or http://127.0.0.1) /// </summary> public string Domain { get; set; } /// <summary> /// Api名称(api/v1/studentinfotest) /// </summary> public string ApiName { get; set; } /// <summary> /// 传入参数名称 /// </summary> public string InputQueryString { get; set; } /// <summary> /// 返回数据类型 /// </summary> public string DataMimeType { get; set; } /// <summary> /// 重写ToString() /// </summary> /// <returns></returns> public override string ToString() { return string.Format("{0}|{1}|{2}|{3}", this.ApiName, this.Domain, this.DataMimeType, this.InputQueryString); } #endregion } }
int b = int.MaxValue; b++;//这里不会抛出异常,b变为-2147483648
unchecked { int a = int.MaxValue; a++;//这里也不会抛出异常,a变成-2147483648 } checked { int a = int.MaxValue; a++;//这里抛出异常,超出最大值 }
默认情况下是uncheck,所以有些情况int值到了最大值添加之后返回了错误的值,这个坑也是需要注意的
8)关于ThreadPool设置最大线程数:
ThreadPool是级不建议用户手动设置最大线程数的:
我们之前出现一个问题,就是这个设置了最大线程数导致的,首先我们设置了10个线程来跑某个请求api的任务,当我们取到了10个任务,通过ThreadPool.QueueUserWorkItem方法将任务排到线程池内,
但是呢我们的任务是请求api的任务,而我们的api都是用的HttpClient来访问的,由于HttpClient中的请求方法都是异步的,这就导致了一个问题,假设我们10个任务都排到了线程池队列中,走到Http请求的那一步的时候,由于HttpClient需要启动一个Task来发送Http请求,而Task也是使用的线程池,但是这个时候线程池中的线程已经用完,没有办法再分配线程,所以这就导致了循环等待,但是如果不用这种方式限制的话该怎么限制呢?
可以使用信号量来控制线程数,每开启一个任务,信号量加1,任务完成的时候-1,当信号量到10的时候就不再执行,等待有空闲任务的时候再执行
9)关于使用redis之后出现的问题:
1、CPU,内存消耗量增大:由于数据都是取自Redis,然后序列化为对象集合,所以序列化过程是一个方面,还有一个就是在并发量比较大的时候产生的拷贝会很多,会导致内存消耗激增,还有就是垃圾回收也变得频繁起来,代很快就满了,就导致cpu要不断进行垃圾回收工作,解决方案:
1、设置二级缓存,先内存,再Redis,这样可以减少序列化次数
2、将缓存细化,将集合按一定的维度分散存储,这样可以减少一次取的数据量减少许多,序列化时间也会大大减小,cpu尖刺也会少了很多
2、关于序列化:使用Redis缓存的时候,很多对象需要序列化为二进制存储到Redis中,然后就必须给实体类上加上[Serializerable]标签,但是加上这个标签之后就出现了一个问题,原先的协议都不通了,WebApi没法收到前端MVC发来的数据(反序列化失败),
后来查明加上标签的类的对象反序列化为json的时候,是按照私有变量进行反序列化的,而不是根据属性来的,所以生成的json与之前的大不一样,反序列化的时候也是如此,所以会导致这个问题,解决方案:
就在上面那段代码里,我反序列化的时候判断了"k__BackingField"这个参数,有的话就采用微软的序列化,否则使用newton的
10) 关于Task.Result和Task.GetAwaiter().GetResult()的区别
他们的区别在于对异常的处理上:如果任务执行过程中发生异常,则Task.Result会将异常包装成一个AggregateException返回,而GetAwatiter().GetResult()则是直接返回原始异常信息