记录日常遇到的坑

  • by20190101 :PackInt的坑,实际是tostring的坑

原因:

  • by20190905,会员发红包 产生红包记录,后来新开了一个供应商表,也走发红包,因为会员id是数值型,会产生会员id重复的问题,红包记录就窜掉了。 这种情况可以在架构上考虑varchar类型储存,固定前缀。后做了特殊逻辑供应商取反。

Redis采坑

  • 涉及到redis使用HashIncrement 精度不对的问题,和double本身有关,而且不是一定出现,可能满足什么条件才会发生精度偏移 需要注意下

  • by20190923,使用缓存统计数据,经常会因为业务处理的问题导致缓存统计受牵连, 解决方案①不要过度信任redis,数据要落库,由真实数据统计出来缓存进redis, 可以在此基础上判断rediskey是否存在而进行增减并落库数据,而不能完全依靠redis做统计,一单出问题就无法修复了。② 使用统一开关,需要的地方接入,一但出现问题, 可以关掉,一会再开(这种可以解决使用会员维度作key的, 无法知道哪些会员有问题,又不能因此而循环会员表清除redis)
  • redis设置全局锁的时候报错:

    StackExchange.Redis.RedisConnectionException: No connection is available to service this operation: SET MQLockf7b4addb0a2f834634d6e03d0a3b043e_3050505_3050603; IOCP: (Busy=0,Free=400,Min=4,Max=400), WORKER: (Busy=40,Free=760,Min=320,Max=800), Local-CPU: n/a
       在 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
       在 StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
       在 SurpriseGame.Common.Redis.RedisInstance.RedisSetNx[T](String key, T value, Int32 seconds) 位置 d:\jk\workspace\8525-jiesan.net.surprise.game.job\SurpriseGame.Common\Redis\RedisHelper.cs:行号 635

StackExchange.Redis.RedisServerException: Endpoint 172.30.108.42:10005 serving hashslot 5212 is not reachable at this point of time. Please check connectTimeout value. If it is low, try increasing it to give the ConnectionMultiplexer a chance to recover from the network disconnect.  IOCP: (Busy=0,Free=400,Min=4,Max=400), WORKER: (Busy=58,Free=742,Min=320,Max=800), Local-CPU: n/a
   在 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
   在 StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
   在 SurpriseGame.Common.Redis.RedisInstance.RedisSetNx[T](String key, T value, Int32 seconds) 位置 d:\jk\workspace\8525-jiesan.net.surprise.game.job\SurpriseGame.Common\Redis\RedisHelper.cs:行号 635

by2019 补充之前踩的:

  • for循环给list add实体, 实体重用的话需要定义在for内部(确保每次都是开辟的新空间), 否则add的全是最后一次的实体地址
  • 关于MongoDB反序列化失败和Json正常
  • MongoDB:修改文档结构后出现错误:Element '' does not match any field or property of class . 在序列化的对象上增加 [BsonIgnoreExtraElements]
  • Json 反序列化和序列化 多字段少字段都没有问题
  • 流水和红包记录对账 ,发现一处问题, 排查天网日志了一个月,只有这一次,看了天梯部署记录, 怀疑是昨天回滚天梯时踩到了mq的坑

  • Q:添加了项目引用 ,代码上也using了 ,生成时报错找不到

A:看看是否生成dll的net版本不一致

  • mysql报错
MySql.Data.MySqlClient.MySqlException (0x80004005): Authentication to host '172.xx.xx.xxx' for user 'TCSURPRISxxxxx' using method 'mysql_native_password' failed with message: Reading from the stream has failed. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Reading from the stream has failed. ---> System.IO.EndOfStreamException: 尝试读取超出流末尾的内容。

MQ采坑

  • mq重复消费导致数据多插,加了防重复验证 结果setnx挂了,导致没写入
  • mq 重复消费

msgid=AC12621600002A9F0000B2D0C4BADCB1

  • mq采坑,mq生产了但没消费

原因是我们新搭建了一个job站点(global文件中启动消费者),同样的代码部署上去了,所以这个新的job站就被当成了一个消费者,但是新的环境有些配置项没弄好(redis,数据库等等方面),造成mq未消费

解决措施:新建一个表,记录(mq消息MsgId,消息内容,消费状态,唯一全局主键),使用唯一全局主键唯一标识一次mq请求, 不能用msgid做消息主键, 因为mq消费失败后退重新生产一个新的msgid,并且主题前缀‘%retry%’,因此需要一个唯一标识来保证同一个消息的唯一性。

接入微信支付

  • 微信推送消息subscribeMessage.send参数类型:phrase 传参中文会报错,只接受汉字

"errcode":47003,"errmsg":"argument invalid! hint: [Mvmw7a04368694]

phrase.DATA汉字5个以内汉字5个以内纯汉字,例如:配送中
  • SHA256 with RSA加密算法问题 (Linux下默认不可以需要装插件, 部署线上windows server2008 R2 也不行)

    [执行时间:10ms][CryptographicException]请求参数:1235|[Time:10]异常内容:System.Security.Cryptography.CryptographicException: 出现了内部错误。
    
       在 System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle provider, Byte[] keyBlob, String format)
       在 System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)
       在 SurpriseGame.Common.WxSignV3.Sign(String message) 位置 d:\jk\workspace\8524-jiesan.net.surprise.game.answer.api\SurpriseGame.Common\WxSignV3.cs:行号 28
/// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string Sign(string message)
        {
            try
            {
                LogBuilder.Info($"请求参数:{message}", "Sign", "Sign");
                // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
                //        亦不包括结尾的-----END PRIVATE KEY-----
                string privateKey = "MIIEvgIBADAN.......9RDdJzFdkgxxgBxmieFkJMBw/BYPH";
                byte[] keyData = Convert.FromBase64String(privateKey);


                //var rsa = GetPrivateKey(keyData);
                //// Create a new RSACryptoServiceProvider
                //var rsaClear = new RSACryptoServiceProvider();
                //// Export RSA parameters from 'rsa' and import them into 'rsaClear'
                //var paras = rsa.ExportParameters(true);
                //rsaClear.ImportParameters(paras);
                //using (var sha256 = new SHA256CryptoServiceProvider())
                //{
                //    var signData = rsa.SignData(Encoding.UTF8.GetBytes(message), sha256);
                //    return BytesToHex(signData);
                //}

                using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
                using (RSACng rsa = new RSACng(cngKey))
                {
                    byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
                    return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
                }
            }
            catch (ArgumentNullException argex)
            {
                LogBuilder.Error($"[ArgumentNullException]请求参数:{message}", argex, "Sign", "Sign");
            }
            catch (PlatformNotSupportedException platex)
            {
                LogBuilder.Error($"[PlatformNotSupportedException]请求参数:{message}", platex, "Sign", "Sign");
            }
            catch (CryptographicException cryex)
            {
                LogBuilder.Error($"[CryptographicException]请求参数:{message}", cryex, "Sign", "Sign");
            }
            catch (Exception ex)
            {
                LogBuilder.Error($"请求参数:{message}", ex, "Sign", "Sign");
                return "";
            }
            return "";
        }

爬虫项目遇到的坑

  • Q1:GDI+中发生一般性错误

A:pictureBox图片显示的时候调用了Image.FormFile("图片地址"),然后 pboxCode.Image=img,图片保存的时候也调用了Image.FromStream(),然后img.Save()的, 问题出在img上了

解决办法pictureBox.ImageLocation="图片地址",图片保存的逻辑不用动

  • Q2:Http响应stream不能读两次及以上!!!!!,需要对响应流处理成string打印出来,同时要对stream解析出包含的html元素

A:用流转成string,然后stringReader读取

  • Q3:登录请求一个login_post.htm页面,会重定向,httpResponse获取不到响应返回的set –cookie

A: 请求http时加上request.AllowAutoRedirect = false;//静止跳转

  • Q4:.net解析Html源代码,获取元素

A: 推荐使用HtmlAgilityPack组件。

  • Q5: cookiecontainer踩坑

httpwebRequest发送两次请求,用cookiecontainer.add存下来。

第一次是

Add进去两条,第二次是

Add进一条,一切和谐。

然后我做了一个把两次请求返回的cookie存下来的动作。

然后用存下来的add进去,第一次add完还是两条。第二次的就不行,验证发现是因为cookie名称重复导致的。

好奇怪,为什么浏览器这样产生的结果就没问题,用模拟的就有问题。

可能是解析方式不一样吧,模拟的是由代码处理的更加严谨。

  • Q6: 找不到或无法加载已注册的 .Net Framework Data Provider

A:如下方法可解决,但是还是优先参照q7配置好,如果还有问题则用这个方法

  • Q7:找不到.Net Framework Data Provider。未安装

A: 需啊在dataaccess层也就是真实用到的地方nuget安装对应版本的,然后项目部署的地方也要安装,因为web.config中配置了mysql的信息,也要安装对应版本

### Git 创建分支问题

Q: 有一次使用git extensions基于develop创建分支,结果发现创建的分支上有qa分支的代码,进过测试发现问题引发原因

A:Git版本3.3.1,使用git 这个方式创建分支的时候需要注意下,切换到develop或master后进行创建时, 光标高亮行一定要在正确的位置, 否则git会使用高亮位置去创建 而不是基于当前分支创建。

可以检查这个来避免问题(如下图就是没问题的)