Common Lisp网站 – 是否可以在不停机的情况下进行更改?

huangapple go评论68阅读模式
英文:

Common Lisp websites - Is it possible to make changes without downtime?

问题

目前,我的主要网站是一个在nginx代理后面的CL可执行文件。

当我进行更改时,我必须创建一个新的可执行文件。停止旧的,然后重新启动新的。随着我的流量增长,这令人担忧。

是否有一种更好的构建系统方法,不需要我停止镜像?

英文:

Right now, my main website is a CL executable behind an nginx proxy.

When I make changes, I have to create a new executable. Stop, the old one and restart the new one. As my traffic grows, this is concerning.

Is there a better buils system approach that doesn't have me stopping the image?

答案1

得分: 2

您可以通过在不同的端口上运行新的可执行文件来最小化停机时间,然后在nginx中切换端口,然后才停止旧的可执行文件。

您也可以尝试以一种可靠的方式组织您的代码,以便您可以可靠地加载/重新加载/卸载部分代码,以将正在运行的镜像转换为一个定义的目标状态,但我不清楚是否存在系统化的方法。有些人曾经在运行时进行了这样的操作,但我认为总的来说,应该尽量使事情具有可重现性。

英文:

You can minimize downtime by running the new executable on a different port, then switch the port in nginx, and only then stopping the old one.

You could also try to organize your code in such a way that you can reliably load/reload/unload only parts to transform your running image to a defined target state, but I am not aware of a systematic approach to that. There have been people who did this on the fly, but I think in general, one should try to make things reproducible.

答案2

得分: 2

Common Lisp的方式是从您的可执行文件创建一个Swank服务器,然后从您家里的Slime连接到它,加载新代码以更新运行中的实例。

提示:https://lispcookbook.github.io/cl-cookbook/debugging.html#remote-debugging

虽然不像部署全新的二进制文件那样稳定,但如果您不在生产环境中开发新代码而是使用本地检出,它应该是可重复的。

无论如何,这是一种有用的方法,可以在生产实例上操作数据,或者在不重新启动的情况下更新设置。

英文:

The Common Lisp way would be to create a Swank server from your executable, connect to it from your Slime at home, and load the new code -to update the running instance.

Hints: https://lispcookbook.github.io/cl-cookbook/debugging.html#remote-debugging

It isn't as solid as deploying a whole new binary, but if you don't develop new code in production without local checkouts, it should be reproducible.

It is anyways a useful method to poke data on the production instance, or update settings without a restart.

答案3

得分: 2

生成一个新的服务器并切换端口是最可靠的解决方案。如果您想要更新实际服务器,至少需要有一个分期服务器来首先测试部署,因为如果您太多次重新定义实际镜像,这可能会引起问题。而且,您可能需要在服务器之间迁移会话:我认为这一步在同一个进程中执行比重新启动另一个服务器更容易。

无论如何,您应该采取防御性措施来清晰地更新您的代码。

假设我定义了这个包:

(defpackage :production (:use :web-api) 
  (:export #:start #:stop #:shutdown #:*server*))

这个包中的start方法启动一个无限循环并将*server*绑定到Web服务器实例。shutdown方法拒绝传入的请求,但仍然处理旧请求。最后,stops终止服务器。

如果您有服务器的新版本,可以执行以下操作:

(rename-package :production :old)
(rename-package :web-api :old-web-api)

通常情况下,系统应该仍然在运行。

如果您现在加载代码的最新版本,使用ql:quickloadasdf:make,您将获得不应干扰现有包的新包。

您可以在不同的端口上启动新服务器,访问数据库等,可能还可以从旧服务器复制状态到新服务器,关闭以前的服务器等。

最后,您可以删除旧的包。

我想要强调的是,在提前采取措施以避免问题的情况下进行实时更新并不是非常安全的,实时编码可能会产生各种不在从头开始加载新状态时看到的效果。但如果做得好,您实际上可以从Lisp的动态性质中受益,例如change-class您的对象或优雅地引入新模块而不干扰运行中的实例。

英文:

Spawning a new server and switching the port is the most robust solution. If you want to update the live server at least you need to have a staging one to test deployment first, because if you redefine the live image too much this can cause problems. And you might need to migrate sessions between servers: this step is easier to do in a the same process I think than by restarting another server.

Anyway, you should take defensive measures to cleanly update your code.

Let's say I define this package:

(defpackage :production (:use :web-api) 
  (:export #:start #:stop #:shutdown #:*server*))

The start method in this package starts an infinite loop and binds *server* to the webserver instance. The shutdown method denies incoming requests but still processes old ones. Finally stops terminates the server.

If you have a new version of your server, you can do:

(rename-package :production :old)
(rename-package :web-api :old-web-api)

Normally the system should still be running.

If you now load the newest version of the code, with ql:quickload or asdf:make, you'll have new packages that should not interfere with the existing ones.

You can start the new server on a different port, access the database, etc. and possible copy state from the old server to the new one, shutdown the previous server, etc.

Finally you can delete the old packages.

What I want to outline is that live updating without taking steps in advance to avoid problems is not very safe, live coding can have various effects that are not seen when loading a new state from scratch. But if you do it well you can actually benefit from the dynamic nature of Lisp to e.g. change-class your objects or gracefully introduce new modules without disrupting the running instance.

huangapple
  • 本文由 发表于 2023年6月19日 17:13:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76505214.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定