[Erlang_Question29]进程收到不是期望的消息时怎么办?

最近在项目中升级了第三方库,导致本应用gen_server中A进程中:

handle_info({add,X},Sum) ->
      {noreply,Sum+X};

结果这么简单的一个工作居然不工作了,一查,发现是第三方库进程B发来的消息由

{add,X}------->{plus,X}

在A进程中存着大量的{plus,X}信息,使得这个进程的内存占用也变得异常的大。

简单修复后,不经意在想:

到底怎么处理那些我们期望不到的消息呢?(这种错误根本就是对方不应该发这种消息给我,根本就不是我自己的错呀

1.你可以记录这些消息:    1a.) as info
    1b.) as warning
    1c.) as error2.对消息进行记数,然后对记数做怎样的处理?
3.直接忽略它们,不做trace?4.让server直接crash掉?

GOOGLE得到MailList里面非常有意思的投票:你是怎么处理与自己进程无关的消息的?

http://erlang.org/pipermail/erlang-questions/2014-August/080420.html

里面的观点大部分都集中于要看该进程的性质:

1.根据进程的生命周期:  如果是短生命周期(生产用完马上销毁)的进程(short-lived),你可以使用不同日志等级来记录这些消息,这将有利于发现真正的问题,不要把问题定位到接收者上,要多关注是谁发给他的,为什么会发到一个错的进程中,这样会造成什么结果?

2. 根据进程的数量:      如果这类进程数量庞大,就直接忽略了,不做trace,避免对日志IO造成压力。

3.根据进程的重要性:    如果是可以处理calls/casts/monitors/exits 消息的进程,我们应该记录下什么消息让他们异常?而其它的大多数进程,我们应该直接忽略它,不做trace。

4. "Let it crash" 哲学: 无论怎样,就是要让其Crash。

以上的”Let it crash"难免有点太牵强,这个错又不是来源于自己,为什么要让别人的错影响到自己,其它的观点很有道理,但Fred(Learn some Erlang的作者)总结非常精彩,分享如下:

I tend to go the log route. There isn‘t a super good reason, but the way
I think about it is a bit of probability.

When do I send messages to the wrong process? A few ideas are:

- Manual debugging
- Typoes
- A Refactoring gone bad
- Initial design got messed up
- Erroneous third-party code that doesn‘t come from my precise
  development right away.

Then the question is what are the consequences I want.

- Manual debugging: do nothing, I‘m poking around
- Typoes: I have to know about these ASAP
- Refactoring gone bad: I have to know about these ASAP
- Initial design got messed up: Something has to be loud and bad
- Third party code: I want the third party to suffer.

For these reasons, I tend to take the following approach:

- In handle_call/3, I log the event with a string a bit like
  "mod=MYMOD at=handle_call warning=unexpected_call msg=~p" and then
  return `{noreply, State}` to force the caller to crash after a
  timeout. It‘s their fault, not mine.
- In other callbacks, just log similar messages, replacing
  at=handle_call with at=handle_cast|info and
  warning=unexpected_cast|info.

I can, from time to time, look at logs for ‘warning=unexpected_*‘ in
logs and see if something is going weird.

If it‘s something happening rarely, I‘m gonna have traces, but without
the weird failures (unless it‘s a call). If it‘s something frequent,
bugs will either show themselves differently, the log volume will be
very high, and so on.

It tends to give me what I need given the circumstances. It‘s not always
as loud as I‘d expect (except for calls, which is ideal), but it tends
to give me enough visibility for the occasional stray message, without
compromising service levels.

具体的不明消息可分为:

--手动Debugging

--手写拼错误

-- 重构代码时出错

-- 原本的设计混乱

-- 第三方代码库引出来错

具体的一种方法可以:

在handle_call/3里面会记录下然后返回:

handlle_call(Msg,_From,State) ->
   log:("mod=~p at=handle_call warning=unexpected_call msg=~p",[?MOdule,Msg]),
   {noreply, State};
强制调用者Crash,这是他们的错,不能怪我.然后反复查看Log中是不是存在‘warning=unexpected_*‘信息。

Running Dialyzer on my codebase:

				
时间: 2024-07-31 14:33:11

[Erlang_Question29]进程收到不是期望的消息时怎么办?的相关文章

操作系统 进程间的通信 之 信号 消息队列 共享内存 浅析

[几个易混淆的相关概念] 进程互斥:指在多道程序环境下,每次只允许一个进程对临界资源进行访问. 进程同步:指多个相关进程在执行次序上的协调. 临界资源:在一段时间内只允许一个进程访问的资源. 临界区:每个进程中访问临界资源的那段代码. [进程通信] 现在常用的进程间通信方式有信号.信号量.消息队列.共享内存.通信,是一个广义的意义,不仅仅指传递一些 message.进程通信就是指不同进程之间进程数据共享和数据交换. [信号和信号量] 信号和信号量是不同的,他们虽然都可用来实现同步和互斥,但信号是

Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> 参考:C和指针学习 说明:本文非常的长,也是为了便于查找和比较,所以放在一起了 Linux 传统的进程间通信有很多,如各类管道.消息队列.内存共享.信号量等等.但它们都无法介于内核态与用户态使用,原因如表 通信方法 无法介于内核态与用户态的原因 管道(不包括命名管道) 局限于父子进程间的通信. 消息队列 在

今天我收到奔跑吧兄弟发来中奖消息是不是真的

今天我收到奔跑吧兄弟发来中奖消息是不是真的[010一5670一8820]人民法院咨询电话:010一5670一8820[人民法院] 温馨提示:(抽奖活动如获奖 请拨打以下法院电话核实):010一5670一8820 法院是国家的一项法律制度.在我国,法院是指国家专门设立的法院机构,根 据法律的规定和当事人的申请,按照法定程序证明法律行为,有法律意义的事件, 文书的真实性和合法性,以及其他与法院有关的法律事务的非诉讼活动. 法院电话::010一5670一8820 法院活动有四大基本特征: (1)法院是

【Linux学习】倒计时退出,当进程收到SIGUSR1信号时开始倒计时,3秒钟后退出程序。

题目3: 编写一个程序实现倒计时退出功能,当进程收到SIGUSR1信号时开始倒计时,3秒钟后退出程序.要求在终端上输出收到信号并开始倒计时的过程如:The process is terminating in 3 sec...The process is terminating in 2 sec...The process is terminating in 1 sec... 1 #include <sys/types.h> 2 #include <unistd.h> 3 #incl

BCB 如何让Application收到SendMessage发送来的消息

一般,都是通过添加一个ApplicationEvent组件就可以接收到PostMessage发来的消息,那么如何收到SendMessage发来的消息呢? https://stackoverflow.com/questions/49862883/sendmessage-to-application-handle-not-working Application有一个Application->HookMainWindow方法 它的参数是这样的事件函数 bool __fastcall CLASSNAME

解决Handler发送消息时:this message is already in use

为了避免在主线程中进行耗时操作,我们经常使用handler来发送消息处理耗时操作. 有时候会出现程序崩溃然后控制台显示this message is already in use的报错信息 报错的信息是指:发送的message正在消息队列中,不能被使用. 其实就是当我们想多次发送消息时,不能使用同一个消息的意思,所以解决的方法就是再次发送的时候重新获取一个新的消息. 注: 不推荐直接使用Message的构造方法创建对象,而是应该通过Message类的静态方法obtain()获取消息对象,该方法会

MFC中如何在TreeCtrl控件中获取鼠标左键消息时的有效点击位置

MFC中,当在TreeCtrl控件中添加鼠标左键消息时,就意味着,凡是在该控件中点击左键后即会响应鼠标左键的消息,可有时我们只想记下有效的鼠标左键点击的事件,如图所示: 只想在CheckBox中点击鼠标左键时,将已选中的Item的句柄存入到链表中,那么如何只将有效的鼠标左键的消息存入链表中呢? 下面是响应鼠标左键消息时从所有鼠标左键消息都响应到只响应有效的左键消息的三个版本: 当响应鼠标左键的消息时,第一个版本: 获取鼠标的点击位置(注意:此时获取的是针对于当前屏幕的鼠标点击位置,所以需要将其转

C# UdpClient使用Receive和BeginReceive接收消息时的不同写法

使用Receive(同步阻塞方式), 注意使用同步方法时,需要使用线程来开始方法,不然会使UI界面卡死 IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 5858); UdpClient udpClient = new UdpClient(RemoteIpEndPoint); while (true) //由于Receive方法是阻塞方法,一个Receive操作完了后才能继续往下执行,所以能在这里使用死循环 { Byte[]

android 进程/线程管理(一)----消息机制的框架

一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统,以事件为驱动的软件系统基本模式都是如下: 程序的入口一般是main: 1.初始化: 比如创建窗口,申请资源等. 2.进入while(true) 在循环中处理各种事件,直到进程退出. 四大组件是进程的部分载体,配置进程在androidmanifest.xml里面,android:process 属性.