隨着項目都遷移到了dotnet core下,阿里的支付寶也需要隨着項目遷移。之前在.Net Framework下用到了阿里提供的AopSdk和F2FPay兩個程序集,支付寶官方提供的只支持Framework,不過還好提供了源碼的下載。
本着不重復造輪子的想法,先NuGet搜了下,已經有不少實現了,仔細比較了下,最終選擇了AliPay.AopSdk.Core。主要原因是在git上開源,再有就是用的人也比較多。
AliPay.AopSdk.Core項目本身很優秀,與阿里官方的Sdk基本完全一致,主要是變更了一些命名不規范的方法。很快修改完成,簡單的測試了下就上線了,卻不想留了個坑。
上線不久,所有用戶無法支付了。登陸服務器(CentOS 7)報的異常是Too many open files in system,額,查下看看先。
ps -ef | grep dotnet 找出服務的pid,這里是14689
cat /proc/14689/limits 看看系統的限制
Max open files 4096 話說已經不少了呀
lsof -p 14689 | wc -l 統計下一共打開了多少,一看,霍,真不少滿了
lsof -p 14689 看下都是哪些,發現有大量的未銷毀的TCP鏈接
看着IP比較眼熟,似乎是阿里的,ping 下支付的服務域名 openapi.alipay.com,嗯,就是它,至此定位到了問題。
先緊急處理下,重啟支付的服務,然后做下配置,把Max open files放大些。因為我的服務是用systemctl管理的,所以只需要配置 xxx.service就好。
在[Service]下面增加一行配置
LimitNOFILE=10240
重啟服務后,重新拿到pid,看下limits,嗯,生效了
先扛着用下,然后來分析問題。
慶幸自己選擇了開源的項目,很容易看代碼。
這兩句,作者實現了池,導致的。然后才回頭開始看項目的文檔,使用說明中用DI注入了一個IAopClient的單例,額,我是每次new出來的,所以xxxxxxxx。
至此似乎解決了,但完全沒有。這個項目單例注入,已經固定了支付寶的商戶號等參數,但我實際的業務需要多個支付寶賬戶,每次根據取到商戶號來賦值。
處理思路:
本來想做個工廠,自己實現個單例,根據不同的商戶號返回不同IAopClient的實現實例。仔細一想以為商戶比較多,仍然存在大量的不必要的鏈接。最后決定,自己拿阿里的源碼,改個core的版本吧。還是重復造輪子了。說干就干,先下個最新的源碼,我這里是alipay-sdk-net-core-3.2.0,新建個dotnet core的Library,把需要的文件copy進來(主要是去掉了Test目錄),編譯下,報錯。源碼中包含了Jayrock,用來處理JSON,git上看了下,好老的項目,已經停止更新了,不知道為什么阿里還在用。不過還好NuGet裝下System.Configuration.ConfigurationManager就一切ok了。還有些warning暫時沒有理會。本機測試下(windows 10),一切OK。放到測試服務器(CentOS 7)上測試下,額,報錯“您使用的私鑰格式錯誤,請檢查RSA私鑰配置,charset = utf-8“,這是什么鬼。看看源碼,不知所蹤。這下比較麻煩了,本機沒問題,遠程測試環境不行,目測肯定是系統的差異了。腦子里蹦出來的辦法--遠程調試。嗯,沒錯,就這么弄(具體遠程調試另一篇文檔)。最后發現,果然是操作系統的差異,RSACryptoServiceProvider這個類,只支持windows系統。找到問題就好辦了,替換掉。具體實現嘛懶了懶,直接拿的Alipay.AopSdk.Core項目中的實現。publish一個版本,到測試服務器上,嗯,問題解決。
非常感謝Alipay.AopSdk.Core項目作者,源碼提供了很大的幫助。
參考資料:
https://github.com/dotnetcore/Alipay.AopSdk.Core
可以使用的版本
https://github.com/draweye/AopSdkCore