[请益] 程式寄信方面的问题

楼主: a47135 (金属史莱姆)   2016-04-08 16:23:35
最近遇到一个问题,所以上来问问看有没有人能解惑
我们的程式有时候会进行大量发信的动作
程式语言是C#,用微软的Exchange.WebServices元件来做发信
发信服务器是他们公司自己架的
我们寄信为了不影响使用者操作,所以寄信都是new一个Thread来做Send Mail的动作
问题来了
有写Log纪录信件对象和信件内容,所以可以确认发出SendMail要求的时候传送的资料是
正确的(信件内容、对象、认证资料等)
当信件发送量过大的时候他们信件服务器寄出的信件的内容和对象偶尔会错乱的情况,像
是寄给A的信件内容却是前一封发给B的信件内容
解决方式就是改成每5秒才做一次寄信动作(之前测2、3秒还是偶尔会有问题)
第一次遇到这种情况,虽然已经解决了,但是很好奇到底是他们家服务器问题还是什么原
因呢?
是否有人可以解惑一下
作者: LaPass (LaPass)   2016-04-08 16:28:00
看起来像是执行绪安全问题
作者: ken1325 (优质水瓶男)   2016-04-08 16:57:00
你们有做lock吗
作者: LaPass (LaPass)   2016-04-08 17:06:00
send_Thread 的宣告跟变动请贴出来
作者: manaup   2016-04-08 17:07:00
程式写成这样 再加上这种说明 九成九是程式有BUG应该就是L大说的问题
作者: LaPass (LaPass)   2016-04-08 17:39:00
private [static] SmtpClient smtp; 问题可能在这里你研究一下 synchronize 怎么用,然后替smtp加上去或是干脆把 static 拿掉,每次都重新建立一次smtp
作者: manaup   2016-04-08 17:45:00
L大是好人 (if u r good @ sth, dont do it for free.
作者: LaPass (LaPass)   2016-04-08 17:46:00
我只有点出问题而已,这个东西要讲清楚的话可是要讲上好几页,他自己去google会比等我打出来快。
作者: sing10407 (阿U)   2016-04-08 17:49:00
答案出来了,static会在memory保留同一个内存位置因此用thread时会一直去改到别人的值,不是独立的物件
作者: LaPass (LaPass)   2016-04-08 17:53:00
其实最好还是先去看一下 SmtpClient 有没有执行绪安全他的javadoc上应该会写,如果没有,那应该就是这边了那就..... 应该是对方的mail server或是更底层的问题了
楼主: a47135 (金属史莱姆)   2016-04-08 18:08:00
的确上百家客户就他们家会这样XD
作者: sing10407 (阿U)   2016-04-08 18:08:00
建议先改改看
楼主: a47135 (金属史莱姆)   2016-04-08 18:16:00
恩,反正那个看起来有点多余,而且改了也不影响结果还是谢谢各位的建议,至少以后程式记得会考虑这方面的问题XD执行绪安全毕业后就变成名词了,比较少考虑到这块XD多谢L大
作者: shadow0326 (非议)   2016-04-08 18:33:00
呃,static members是thread-safe那句话后面还有一句instance members不保证是thread-safe
作者: qrtt1 (有些事,有时候。。。)   2016-04-08 18:35:00
InitSMTP_MailMassage 为何不直接回传 message_SMTP而却是跟其他 method 共用这个变量!?
作者: shadow0326 (非议)   2016-04-08 18:36:00
你可能把那句话误会成static SmtpClient instance是thread-safe的...那误会可大了现在是讲该类别自己的成员(也就是该物件自己的state)跟传进的参数无关啊
作者: chrischen (一个人的长假)   2016-04-08 18:56:00
共用变量+race codition,问题在那堆底线开头的变量
作者: x000032001 (版废了该走了)   2016-04-08 19:13:00
重点是member..就是这class底下的变量 不是讲他自身不是你把SmtpClient宣告public static 他就很安全了
作者: gn01838335 (寂静的生存者)   2016-04-08 19:36:00
static 或 资源竞争 对于某事情A未处理完被B抢走资源 没有singleton研判最后寄mail地方可能是关键,写个log记录所有寄信和内容从这方向查感觉比较能抓到问题
作者: alog (A肉哥)   2016-04-08 20:26:00
你们去买mailgun然后把smtp换成mailgun提供的服务器 送送看你们所谓的大量邮件如果会出错 是你们程式错 如果没有错 就是对方的smtp server有问题看一下email source code有没有email server版本*smtp 版本资讯然后在搜寻一下是不是他们smtp server是不是版本没更新或看这软件有没有changelog有记载这类问题的
作者: chrischen (一个人的长假)   2016-04-09 09:02:00
没贴完整code 用猜的看不准 丢到github公开review吧
作者: lovdkkkk (dk)   2016-04-09 10:38:00
这写法它是 thread safe 也没有用啊 0rz在 Init_SMTPClient 它会不断地被换成新的实体要写 log 直接开 smtp 本身的送信记录 log 最准要测可以把间隔缩成 0 秒看别家会不会也出问题 XD
作者: evanslify (evs)   2016-04-09 17:48:00
直觉觉得, 你踩到雷; 如果间隔0会不会100%出错?
作者: brucetu (sec)   2016-04-09 20:20:00
log应该留在最后面,现在这样不是等于白留了吗?还有为什么不改成固定用一个thread发就好,要每一个寄信动作都用一个新的thread呢 徒增race condiction的可能性没有信要送的时候就sleep,耗用的资源基本是0另外… 上个跟list传值有关的解释The澑eference湶s passThe澑eference湶s passed毪y value.Arrays in .NET are oThe reference is passed by valueArrays in .net are object on the heap, so you have a reference. That reference is passed by value, meaning that changes to the氲ontents漑f themeaning that changes to the contrnts of the array will be seen by the caller ,but reassigning the array wont.似乎代表着,你建构一个mail,传cc的list 进去之后,呼叫send start一呼叫 mail.send ,start 一个new thread,接着读取下一份资料,准备建构新的mail,这时如果外层没有assign一个新的list给cc,而是把原本的ccList直接clear再add ,就会修改到前一个mail的_cc 因为都是指向同一个list,所以在mail建构的那边应该对list做个clone比较安全,虽然你不一定会碰到这个问题发生。我还是觉得用一条线程去发就好了…
作者: lovdkkkk (dk)   2016-04-09 20:56:00
同楼上, 一条慢慢的一封一封寄就好了 @@
作者: brucetu (sec)   2016-04-09 21:57:00
只用一条线程循环处理所有要寄的信 也不会多慢吧,绝对比现在五秒发一封快,不然就是好好检查把资料传递切干净,也许其他客户没有出问题是因为他们没发现?例如根本没有check或者讯息内容非常雷同 寄错人也不会发现
作者: psliurt (反指标)   2016-04-10 12:48:00
哀 问题就是那个static smtpclient我觉得你先把执行绪跟何谓执行绪安全搞清楚
作者: YahooTaiwan (超可爱南西我老婆)   2016-04-10 19:02:00
既然每次送信都要 new smtpclient,干嘛放 static ???感觉你不是很了解 static 的特性与用途

Links booklink

Contact Us: admin [ a t ] ucptt.com