Reprinted: http://www.cnblogs.com/me-sa/archive/2011/10/29/erlang0010.html
Erlang originated from the telecom industry. Joe Armstrong mentioned the design requirements of Erlang.Software maintenance should be performed without stopping the system. In practice, we also benefited a lot from this kind of continuous service hot update, and finally we don't need to wait until there is no one in the middle of the night to update again. So how do we do hot update? How does Erlang achieve hot update? This is the question we will answer in this article.
How to perform hot updates?
For more information about hot Update (hot_swap), see Wikipedia: http://en.wikipedia.org/wiki/hot_swapping. How can erlangbe be updated? In fact, the Erlang document provides an example of hot update on multiple nodes when describing the RPC module:
% Find object code for module mod
{Mod, bin, file} = Code: get_object_code (MOD ),
% And load it on all nodes including this one
{Resl, _} = RPC: multicall (Code, load_binary, [mod, bin, file,]),
% And then maybe check the resl list.
% If you are performing hot update on a specified node, you can also do this:
{_ Module, binary, filename} = Code: get_object_code (module ),
RPC: Call (node, code, load_binary, [module, filename, binary])
% We can also do this:
Network_load (module)->
{_ Module, binary, filename} = Code: get_object_code (module ),
[RPC: Call (node, code, load_binary, [module, filename, binary]) | node <-nodes ()],
OK.
Network_load (node, module)->
{_ Module, binary, filename} = Code: get_object_code (module ),
RPC: Call (node, code, load_binary, [module, filename, binary]),
OK.
Let's take a look at the above Code. The Code: get_object_code (MOD) method queries the code path to locate the location of the specified module. The returned value is {module, binary, filename}, that is, {Module name, module binary data, module File Information }. after this method is executed, we obtain the metadata and binary data of the specified module, followed by loading the new module through code: load_library/3. after the load_library method is executed, the hot update is completed. so what happened after these operations?
How to do it?
The secrets of Erlang hot update are actually concentrated in the Code module. The Code module is the external interface exposed by Erlang code server. Its responsibility is to load the compiled modules to the runtime environment of Erlang.
How is the code loaded?
The system can be started in embedded or interactive modes. The default mode is interactive mode. The two modes differ greatly in the module loading policy: the embedded mode is restricted by application scenarios. The module loading requires displaying the order in which the specified code server loads the module, for example, loading according to the startup script. in interactive mode, only part of the code is loaded when the system is started. It is usually a module that you need during running. other code modules are dynamically loaded when they are used for the first time. when you call a method, you find that a module is not loaded, and the code server searches for and loads the module.
How is this search performed? In interactive mode, code server maintains a list of search code paths, usually called code paths. the set_path (PATH) get_path () add_path (DIR) add_pathz (DIR) add_patha (DIR) of the Code module is used to manage the code path. the folders related to kernel and stdlib are loaded first. If the subsequent modules have the same name as the OTP module, they will be overwritten by the modules with the same name in OTP; in other words, the modules in kernel and stdlib will not be overwritten.
Erlang Runtime is a prerequisite for normal operation of the Code server. Hot Updates also depend on the stability and reliability of this infrastructure. to prevent the re-loaded module from affecting the runtime itself, the three folders kernel stdlib compiler are marked as sticky. this means that if you try to reload these modules, a warning will be issued and the execution will be rejected. cancel the sticky folder and use the-nostick option. the Code module provides the stick_dir (DIR) unstick_dir (DIR) is_sticky (module) method to check whether a folder is sticky.
How is the code version switched?
The code version has two concepts: the current version code 'current' and the old version code 'old'. Once the module is loaded, it becomes 'current' and another version is loaded, the previous version is changed to 'old', and the new version is changed to 'current '. at this time, the two versions still exist at the same time, and the new version will be used when new requests are executed, the old version of the Code will also be used because there are other modules calling the 'old' version (for example, there is a timer in the middle of the method: sleep will cause the process to reside in this method ). if you perform another hot update, the third instance will be loaded, and the code server will terminate the process that is still resident in the 'old' version code dependency. then the third instance becomes 'current ', and the 'current' of the previous version is marked as 'old '.
There is a purge (module) method in the Code module, which is used to clear the old version of the module and remove the version marked as 'old'. If a process is occupying the old version of the Code, these processes will be killed first. there is also a soft_purge method, which only processes the unoccupied 'old' version of the code. the Code module also has some methods to view version conflicts and check the module loading status;
To sum up, Erlang uses the coexistence of two versions to ensure that a version is always available at a certain time, so that external services will not be stopped, the new version will be automatically used in subsequent calls. If multiple instances exist in the same module, they will still be replaced according to the rules of the new and old versions.
The following code snippets of two open-source projects show some applications of the Erlang code module in hot update:
The first is mochiweb (Address: git: // github.com/mochi/mochiweb.git). The reloader module of the Project is responsible for automatically reloading modified modules. Let's look at its reload-related code:
Reload_modules (modules)->
[Begin code: purge (M), Code: load_file (m) end | M <-modules].
Reload (module)->
IO: Format ("reloading ~ P... ", [module]),
Code: purge (module ),
Case code: load_file (module)
{Module, module}->
IO: Format ("OK .~ N "),
Case Erlang: function_exported (module, test, 0)
True->
IO: Format ("-calling ~ P: Test ()... ", [module]),
Case catch module: Test ()
OK->
IO: Format ("OK .~ N "),
Reload;
Reason->
IO: Format ("fail :~ P .~ N ", [reason]),
Reload_but_test_failed
End;
False->
Reload
End;
{Error, reason}->
IO: Format ("fail :~ P .~ N ", [reason]),
Error
End.
In another project, we see smerl (Address: http://code.google.com/p/smerl/), which is positioned as simple metaprogramming for Erlang, which is more flexible and can even be like this:
Test_smerl ()->
M1 = smerl: New (FOO ),
{OK, M2} = smerl: add_func (M1, "bar ()-> 1 + 1 ."),
Smerl: Compile (m2 ),
Foo: bar (), % returns 2''
Smerl: has_func (M2, bar, 0). % returns true
In the compile method of smerl, we still use the familiar code: purge (module) and Erlang: load_module (module, BIN) methods.
This is the day of the week. Have a good weekend. [gift! You | gift <-[good_night, happy, good_luck].