9 ms·
Hot code reloading is really amazing in Erlang. We use it to patch a method without restarting on a regular basis. Getting reltool properly configured to deploy
by rubyrescue 13y ago
Hot code reloading is really amazing in Erlang. We use it to patch a method without restarting on a regular basis. Getting reltool properly configured to deploy the new version of your application though is a MAJOR pain in the ass.
for the non-erlangers:
the 'simple' way (ie i have a tiny change i want to make, so i'll just ssh in and do it) is to just edit your code, then attach to an existing node, and do make:all([load]) to pick up the code changes. we added a makefile "make attach" that does this for us.
the 'reltool' way is you package your application into releases. We use jenkins build numbers as the third digit in our releases, so each one is packaged into a zip, encrypted, and then is ready to deploy. at deploy time, the zip is copied to all machines, then we use some escript to attach to the running nodes, and use the 'release_handler' bring up the N+1 version of our app. it's a pain but once it's configured it's amazing...
- tel 13y agoI would love to see more information about how you guys configured reltool. I really loved using hot code reloads in Erlang, but always did them manually during development. I could get releases to work, but never felt confident in how to use them properly.
- rubyrescue 13y agosounds good. i'm about to start a whisper tech blog and we can do that as our first post...
- _nato_ 13y agoI am excited about a new kid on the block for releases: http://relx.org/ http://relx.org/
- vladimirralev 13y agoDo you have some sort of guidelines when and when not to do hot release upgrade? I still have to find anybody shipping whole updatable releases with erlang - couchdb, rabbitmq, any big open source project, nobody is doing it. I think it's a bit overrated, because realistically nobody will want to do this in production, unless it is audited and tested in every possible way. If you have to update external resources with the code_change callback it can fail miserably. I have no problem using it in production for small changes that I fully understand, but big release - wouldn't do it. Too many things can go wrong at the same time to react. You have to audit and test the upgrade and the rollback, which means extra code in code_change to handle the rollback too. Quite heavy.
- blankverse 13y agoYes, I could not find any examples. Would be great to find out real world examples of people using erlang's hot code reloading in production.
- mulligan 13y agoMochi Media uses hot code loading in production.
- blankverse 13y agoCould you talk a little bit about what happens to processes which are running different versions of the code? Do you make your code backward compatible so that old processes continue to work with the new process? Or do you just let the old processes crash?
- strmpnk 13y agoYou can upgrade state in many cases if the changes are trivial, though depending on the ephemerality of a process you might let it finish or crash and restart instead of doing this.
- blankverse 13y agoSo, in the worst case, for achieving basic code reloading in other erlang like systems(ex.- cloud haskell), we could let every process in the cluster crash and restart with the new version?
- strmpnk 13y agoIt's rarely "only crash" as that eventually bubbles up to being equivalent to a reboot. It's simply that you can have subsystems that do that in effective isolation if the effects of a reboot are minimal. On the code state upgrade side there are usually a few different issues that can arise and I'd be very curious to hear if there are ways Haskell would handle some of these. The first one is type changes. I might have a record that has a new field added. Now it's not necessarily pretty to upgrade on call with a pattern match or using a code upgrade protocol but it's easily expressed dynamically. Another is in the interface, like adding new arguments or changing from a synchronous call to an asynchronous one. These are a bit easier to handle via indirection though they show that you'll need to plan your entry/exit points for upgrades carefully (again, OTP has things like gen_server which make this much easier). If Haskell can manage to get past they type boundary issue then it's really a matter of supporting at least 2 simultaneous versions of code so each process can be scheduled and upgraded in natural course. Handling more than 2 could be of use depending on how aggressively you want to purge, for example, a local rather than fully qualified call can be caught in a closure and passed around as in some value to be called later. These long lived references will need to be handled carefully or you might get some delayed surprises.