Reloading code on a clojure production server

What is the best way to get the new code to the production ring server without restarting the entire JVM?

I currently use wrap-reload in production, but this doesn’t work for me, because sometimes I want to run commands in repl (for example, when migrating databases), before starting a call, it will start processing requests using new code. In addition, various blogs and tutorials say that reloading should not be used in the production process, although I do not understand why not.

I came up with the following solution, but I confess I do not have a deep understanding of what is happening under the hood. I was wondering if I can get a test of the performance of whoever does this. Does this method seem reasonable?

The idea is to have a path (/ admin / reload-clj) that causes all clojure code to reload.

(defonce ^:dynamic *jetty*) (declare reload-clj) (defn app [req] ... (when (= (req :uri) "/admin/reload-clj") (reload-clj req)) ...) (defn start-jetty [] (let [j (run-jetty app {:port (http-port) :join? false :max-threads 16})] (dosync (ref-set *jetty* j)) j)) (defn reload-clj [req] (future (log/info "Reloading clojure code...") (require '(whrusrv admin main utils wdb) :reload-all) (.stop @*jetty*) (start-jetty) (log/info "Clojure reload success!")) {:status 200 :headers {"Content-Type" "text/plain"} :body "Reloading..."}) (defn -main [& args] (start-jetty)) 
+8
clojure ring
source share
2 answers

The code you have will work, although you should know that :reload-all only loads the namespace and these namespaces. It does not recursively load dependencies of these namespaces.

I must add that rebooting this way is not highly recommended on a production system.

Newly deployed code may have errors that are not explicit until the system restart (for example, they depend on var, which is still detected from the running system, but whose declaration has been deleted). The system will work fine, but then reboot.

Download code can also have side effects that can ruin your production environment. Although his good style is to avoid this, the only way to truly make sure that something unexpected does not happen is to restart the JVM.

The best way to perform a zero-downtime deployment in the JVM is with load balancing deployment.

+6
source share

I had an intranet web service in general lisp on a previous job, so I don't know if this is consistent as production. Also, being in CL, my answer is neither ring nor clojure specific. However, it is useful for reloading code.

What I did was run a smart server (part of slime) on the lisp instance and connect to it even remotely from my desktop. That way I could write new code, rewrite code, debug, reload, etc. Obviously, in a real production system, you will have to be especially careful.

You can do the same in clojure, you even have swank alternatives like nrepl for example.

You also need to consider security and allow only local connections or something for you.

+2
source share

All Articles