>>Agenda:

>>Ⅰ.国庆假期问题出现

>>Ⅱ.双休日异常再次出现

>>Ⅲ.排障

>>Ⅳ.异常复盘

>>Ⅴ.修复后监测

>>Ⅵ.结束

Ⅰ.国庆假期问题出现TOP

国庆假期期间——10月5号——发现支付中心频繁报异常“System.NullReferenceException: 未将对象引用设置到对象的实例。”,通过分析异常堆栈信息,代码出现在QRCodeService的GetQRCode方法里如下第8行代码:

 /// <summary>
/// 扫码支付 获取支付码
/// </summary>
/// <param name="reqModel"></param>
/// <returns></returns>
public ResponseModelBase GetQRCode(QRCodeRequestModel reqModel)
{
AutoMapper.Mapper.CreateMap<QRCodeRequestModel, QRCodeRequestDTO>();
var reqDto = AutoMapper.Mapper.Map<QRCodeRequestDTO>(reqModel);
if (reqDto.valid_minutes == )
{
reqDto.valid_minutes = ;//默认设置为20分钟
} if (string.IsNullOrEmpty(reqModel.order_no))
{
throw new ResponseErrorException("未获取订单ID,请重新检查订单信息");
}
if (reqModel.pay_money <= )
{
throw new ResponseErrorException("订单价格有误,请重新验证该订单");
}
if (string.IsNullOrEmpty(reqModel.goods_name))
......
......
}

异常日志:

 // ::    [GetQRCode_140340241_DCB85]请求支付中心参数:{"biz_system":"","goods_name":"W17720171005140403733142/qdrpayment3577421317952512T/","merchant_id":"102573307097-102125439412","notify_url":"http://papi1.shenbianhui.cn//OrderPayBack/BackResult","order_no":"DD2017100500470030","order_time":"","pay_channel":"","pay_money":"","remark":"","return_url":"http://120.55.16.195/pay/returnYimeiCallBack.do","sign":"de101b203758cbbe7f83ce04f20d6fb1","third_pay_platform":"","valid_minutes":""}
// :: [GetQRCode_140340241_DCB85]支付中心验签通过。
// :: [GetQRCode_140340241_DCB85]获取二维码进入
// :: [GetQRCode_140340241_DCB85]系统异常:System.NullReferenceException: 未将对象引用设置到对象的实例。
在 AutoMapper.TypeMapFactory.<>c__DisplayClass3_0.<MapDestinationPropertyToSource>b__0(IMemberConfiguration _)
在 System.Linq.Enumerable.Any[TSource](IEnumerable` source, Func` predicate)
在 AutoMapper.TypeMapFactory.CreateTypeMap(Type sourceType, Type destinationType, IProfileConfiguration options, MemberList memberList)
在 AutoMapper.ConfigurationStore.<>c__DisplayClass80_0.<CreateTypeMap>b__0(TypePair tp)
在 System.Collections.Concurrent.ConcurrentDictionary`.GetOrAdd(TKey key, Func` valueFactory)
在 AutoMapper.ConfigurationStore.CreateMap[TSource,TDestination](String profileName, MemberList memberList)
在 PaymentService.QRCodeService.GetQRCode(QRCodeRequestModel reqModel)
在 PaymentPlatform.QRCode.GetQRCode.MyBiz(String requestJson)
在 PaymentPlatform.QRCode.HandlerBase.ProcessRequest(HttpContext context)

从第9行有ConcurrentDictionary,难不成是并发导致的?当时系统TPS并发在50以上。

系统运行数月来,以前从未遇到这样的问题呢。

进一步排查,这个异常出现之后,后面所有对这个接口的请求处理都报这个异常。另外,三个负载节点中,只有其中的9177节点接连报这个异常。

直觉怀疑,随着线上每周一两次的发版,会不会是3个节点AutoMapper.DLL版本不一致呢。为了将影响减到最低,紧急联系运维,将9177节点的站点文件删掉,从其他节点copy过来一份。 运维告知处理完毕后,问题未再复现。

此后的几天,线上也没有再发生类似事故。我也因此认为是文件版本问题所致,就不再关注。

Ⅱ.双休日异常再次出现TOP

谁知,就在上周末的两天,这个异常又出现了,还是出现在9177节点。

那这回,就不能理解了。文件版本应该是一致了呀。

迅速联系运维,帮忙回收一下站点的应用程序池。

谁知回收完后,问题依旧。

咨询运维,为什么只有这个节点报这个异常,运维披露10月5号也并未copy文件,只是重启了一下iis。

那只好应急让运维再重启一下iis了。 此事暂时平息。

Ⅲ.排障TOP

为了可以消停地过下个周末,决定今天把这个问题根治一下。

大家初步的分析是,AutoMapper.Mapper.CreateMap是静态方法,多线程时可能会出现问题。

其实我也一直知道,AutoMapper建议把映射关系在程序启动时做一次性初始化,而非在每次转换对象时都做初始化。

只不过我当时在用AutoMapper时,并未重视这一点。就写成了每次都是先创建映射接着转换对象。

欠下的账总是要还的。 系统此前没出现这样的异常,只能说时间不到。

就像墨菲定理说的,该发生的事情总会发生。 这不,不早不晚,就在国庆节和上周末两个节假日出现了。

Ⅳ.异常复盘TOP

有必要复现一下那个异常。当然,小概率问题,并不容易测出来。

好在,我有JMeter。

在项目里新建了AutoMapperTest.ashx文件,ProcessRequest方法体如下:

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain"; LogHelperUtil logHelper = new LogHelperUtil("", LogType.HFAgentPayService);
LogHelper.Write("[AutoMapperTest]"); Thread.Sleep(new Random().Next(, )); try
{
QRCodeRequestModel reqModel = new QRCodeRequestModel(); AutoMapper.Mapper.CreateMap<QRCodeRequestModel, QRCodeRequestDTO>();
var reqDto = AutoMapper.Mapper.Map<QRCodeRequestDTO>(reqModel); Thread.Sleep(new Random().Next(, ));
context.Response.Write(JsonConvert.SerializeObject(reqDto));
}
catch (Exception ex)
{
logHelper.Write("[AutoMapperTestException]" + ex.ToString());
context.Response.Write(ex.ToString());
}
}

发布到测试环境。

接下来,创建JMeter的测试计划,模拟1000个线程数来压测这个ashx。

持续执行了20分钟。

过程中,如下两件事,使得那个诡异的bug终于从洞里钻出来了:

  • 重新覆盖了一下站点的文件,AutoMapper.Mapper.CreateMap语句出现如下异常,在11:08:08这一秒出现了160次。
2017/10/17 11:08:08	[AutoMapperTestException]System.InvalidOperationException: 集合已修改;可能无法执行枚举操作。
在 System.Collections.Generic.List`1.Enumerator.MoveNextRare()
在 System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
在 AutoMapper.TypeMapFactory.CreateTypeMap(Type sourceType, Type destinationType, IProfileConfiguration options, MemberList memberList)
在 AutoMapper.ConfigurationStore.<>c__DisplayClass80_0.<CreateTypeMap>b__0(TypePair tp)
在 System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
在 AutoMapper.ConfigurationStore.CreateMap[TSource,TDestination](String profileName, MemberList memberList)
在 PaymentPlatform.Test.AutoMapperTest.ProcessRequest(HttpContext context)
  • 中午找运维手动回收了一下应用程序池,AutoMapper.Mapper.CreateMap语句出现如下异常,和节假日出现的异常一样!这个异常在12:02:04~12:03:17之间出现了43351次。   默认情况下,iis会在每间隔固定时间29小时回收appPool,如果此时正好有许多请求在访问此接口,那么必然也会引发AutoMapper的这个异常。这大概就能解释为什么线上出现这个bug了。
2017/10/17 12:02:04	[AutoMapperTestException]System.NullReferenceException: 未将对象引用设置到对象的实例。
在 AutoMapper.TypeMapFactory.<>c__DisplayClass3_0.<MapDestinationPropertyToSource>b__0(IMemberConfiguration _)
在 System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
在 AutoMapper.TypeMapFactory.CreateTypeMap(Type sourceType, Type destinationType, IProfileConfiguration options, MemberList memberList)
在 AutoMapper.ConfigurationStore.<>c__DisplayClass80_0.<CreateTypeMap>b__0(TypePair tp)
在 System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
在 AutoMapper.ConfigurationStore.CreateMap[TSource,TDestination](String profileName, MemberList memberList)
在 PaymentPlatform.Test.AutoMapperTest.ProcessRequest(HttpContext context)

贴上JMeter压测截图:

贴上IIS应用程序池的回收配置:

Ⅴ.修复后监测TOP

正如第《Ⅲ.排障》节所说,解决方案就是在全局的Application_Start时,定义所有的AutoMapper类型映射。这样,就保证了映射关系的一次性初始化。后续代码不需再定义,只关注对象转换就可以了。

发布到测试环境。

再次启动JMeter测试计划,14分钟内,无论在压测过程中更新文件,还是回收站点应用程序池,都未出现那些并发请求所带来的AutoMapper创建类型映射的异常。

Ⅵ.结束 TOP

再次强调,你应该尽量统一管理AutoMapper的映射定义并且只做一次性初始化。

在博客园的一篇AutoMapper的《AutoMapper 最佳实践》文章中介绍:

虽然AutoMapper并不强制要求在程序启动时一次性提供所有配置,但是这样做有如下好处:
a) 可以在程序启动时对所有的配置进行严格的验证(后文详述)。
b) 可以统一指定DTO向Entity映射时的通用行为(后文详述)。
c) 逻辑内聚:新增配置时方便模仿以前写过的配置;对项目中一共有多少DTO以及它们与实体的映射关系也容易有直观的把握。

AutoMapper.Mapper.CreateMap报“System.NullReferenceException: 未将对象引用设置到对象的实例。”异常复现的更多相关文章

  1. silverlight 报 System.NullReferenceException 未将对象引用设置到对象的实例。

    在 Microsoft.Windows.Design.Platform.SilverlightMetadataContext.SilverlightXamlExtensionImplementatio ...

  2. 报警提示 System.NullReferenceException:“未将对象引用设置到对象的实例。

    System.NullReferenceException:“未将对象引用设置到对象的实例.是就因为Session在记录到服务器时,没有添加  IRequiresSessionState 所以运行时回 ...

  3. C# WinForm程序添加引用后调用静态方法时报“Interfaces_Helper.Global”的类型初始值设定项引发异常。---> System.NullReferenceException: 未将对象引用设置到对象的实例。

    出现原因: 因为Global类初始化某个静态变量时没有成功则会抛 System.NullReferenceException 异常,具体代码: public static string connstr ...

  4. VS2019,打开项目之后显示:System.NullReferenceException: 未将对象引用设置到对象的实例

    关闭项目,删除项目文件夹下的隐藏文件夹.vs和bin/obj文件夹

  5. 【小错误】WPF代码报错:未将对象引用设置到对象的实例。

    今天编写动态创建Image对象的代码时候,报出了下面的错误: 起初还以为我创建的BitmapImage对象出现了问题,设置断点调试了下代码发现BitmapImage里面是有数据的. 我就郁闷了,后来发 ...

  6. Spring.Net 未将对象引用设置到对象的实例

    “/”应用程序中的服务器错误. 未将对象引用设置到对象的实例. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详 ...

  7. mvc “System.NullReferenceException”类型的异常在 App_Web_zo44wdaq.dll 中发生,但未在用户代码中进行处理 其他信息: 未将对象引用设置到对象的实例。

    “System.NullReferenceException”类型的异常在 App_Web_zo44wdaq.dll 中发生,但未在用户代码中进行处理 其他信息: 未将对象引用设置到对象的实例. 解决 ...

  8. P/Invoke出现错误 System.NullReferenceException”类型的未经处理的异常在 未知模块。 中发生 未将对象引用设置到对象的实例。

    问题 “System.NullReferenceException”类型的未经处理的异常在 未知模块. 中发生 未将对象引用设置到对象的实例. 解决方案 1.尝试 用管理员身份运行CMD,输入nets ...

  9. C#一般处理程序设置和读取session(session报错“未将对象引用设置到对象的实例”解决)

    登陆模块时,用到了session和cookie.在一般处理程序中处理session,一直报错.最后找到问题原因是需要调用 irequiressessionstate接口. 在ashx文件中,设置ses ...

随机推荐

  1. bitcoinj学习记录

    一.密码学相关资料 使用Bouncy Castle生成数字签名.数字信封 ECDH and ECDSA(ECC椭圆曲线算法3) 数字签名算法RSA与 ECDSA的比较与分析 Java密码学 非对称加密 ...

  2. [No0000112]ComputerInfo,C#获取计算机信息(cpu使用率,内存占用率,硬盘,网络信息)

    github地址:https://github.com/charygao/SmsComputerMonitor 软件用于实时监控当前系统资源等情况,并调用接口,当资源被超额占用时,发送警报到个人手机: ...

  3. Ubuntu下文件所属用户的说明

    最近做项目发现,当你使用sudo建立新的文件或者目录时,该文件的所有者是root用户,此种情况下,使用tensorflow加速就会报错,除非你把文件的权限改成777,但是这样不安全. 纠正的做法是,建 ...

  4. 一种历史详细记录表,完整实现:CommonOperateLog 详细记录某用户、某时间、对某表、某主键、某字段的修改(新旧值

    一种历史详细记录表,完整实现:CommonOperateLog 详细记录某用户.某时间.对某表.某主键.某字段的修改(新旧值). 特别适用于订单历史记录.重要财务记录.审批流记录 表设计: names ...

  5. [skill][http] http管道化连接

    已知http的请求响应是一对一的. 就是一个请求跟着接下来的响应便是与之配对了. 而另一种方式, 可以依靠顺序, 即发送多个http请求, 然后返回对个http响应. 严格按照顺序将他们对应起来, 称 ...

  6. <笔记>Effective Objective-C 2.0 编写高质量iOS与

    1. 内存管理-引用计数 2. 非对象类型  int float double char 3.运行时--编译器(编译时)函数调用 4.@class  缩短编译时间,降低依赖,耦合 5.使用字面量而不是 ...

  7. 20165336 实验一 Java开发环境的熟悉

    20165336 实验一 Java开发环境的熟悉 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:康志强 学号:20165336 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验 ...

  8. 手工sql注入简单入门

    1.判断是否可以注入: 数字型: 1.1在参数后面加一个引号',如果页面报数字number错误,则一定不是sql注入点:如果报数据库比如mysql.oracle之类的错误,则是一个sql注入点. 1. ...

  9. 关于webpack,babel,以及es6和commonJS之间的联系(转)

    add by zhj: babel是将es6转为es5,而webpack从名字也能看出来,是一个打包工具,根据文件之间的依赖关系,将文件进行打包 原文:https://blog.csdn.net/a2 ...

  10. jquery实现简单的弹出框

    弹出框本身是一个div,默认是隐藏不展示的,在需要弹框的时候使其显示,并浮在当前页面之上 弹框样式: .tanchuang { width: 100%; height: 100%; display: ...