最近在开发过程中遇到一个问题,大概是这样的,原先一个worker进程,现在要改成可以随时去掉,也可以随时在重启,这个进程的supervisor是one_for_one类型的,如果不改变supervisor的类型(代码里面很多都是用这个supervisor的,改supervisor不好),这样就引发了一个问题,实验证明如下:
如果一个supervisor是simple_one_for_one,你无论使用多少次supervisor:start_child(Super, Arg)都不会有问题,但是如果是其他的,比如one_for_one,使用supervisor:start_child(Super, {ID, {M, F, A}, Restart, ShutDown, Type, Args}),只要ID一样第二次就报错了,[{error,{already_started,<0.844.0>}}]。其实很好理解one_for_one的情况下,ChildID什么的都是自己定好的,如果相同的ChildID,spervisor不会接受。simple_one_for_one什么的是动态加载的,ID什么的应该他内部有方法解决了。
既然如此那么解决方法也就有了,弄一个simple_one_for_one的supervisor,那个需要随时重启和去掉的worker进程就挂载在这个新的supervisor下,这样就能解决ChildID冲突了。如果偷懒不想新弄一个supevisor,那就在start这个worker前,加上supervisor:delete_child(Super, ChildID)。这个东西的作用就是,如果ChildID的进程是running或者restart的,那就会返回错误;如果ChildID的进程是死的,那就会释放这个ChildID给下次start_child时候用。
还有一个需要注意的是,既然要随时去掉和重启,那么start_child的参数什么的要注意了,设置重启策略为不重启或者其他,具体参数解释:传送门http://blog.youkuaiyun.com/xum2008/article/details/9288411 ;
如果一个supervisor是simple_one_for_one,你无论使用多少次supervisor:start_child(Super, Arg)都不会有问题,但是如果是其他的,比如one_for_one,使用supervisor:start_child(Super, {ID, {M, F, A}, Restart, ShutDown, Type, Args}),只要ID一样第二次就报错了,[{error,{already_started,<0.844.0>}}]。其实很好理解one_for_one的情况下,ChildID什么的都是自己定好的,如果相同的ChildID,spervisor不会接受。simple_one_for_one什么的是动态加载的,ID什么的应该他内部有方法解决了。
既然如此那么解决方法也就有了,弄一个simple_one_for_one的supervisor,那个需要随时重启和去掉的worker进程就挂载在这个新的supervisor下,这样就能解决ChildID冲突了。如果偷懒不想新弄一个supevisor,那就在start这个worker前,加上supervisor:delete_child(Super, ChildID)。这个东西的作用就是,如果ChildID的进程是running或者restart的,那就会返回错误;如果ChildID的进程是死的,那就会释放这个ChildID给下次start_child时候用。
还有一个需要注意的是,既然要随时去掉和重启,那么start_child的参数什么的要注意了,设置重启策略为不重启或者其他,具体参数解释:传送门http://blog.youkuaiyun.com/xum2008/article/details/9288411 ;