更新符号链接指向的JAR文件时,进程正在运行,这样做是否安全?

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

Is it safe to update a symlink to a jar while the process is running?

问题

所以,我正在考虑为我的流程设置部署脚本,使其指向一个符号链接,该符号链接指向我应用程序的最新版本的 jar 文件。

因此:

符号链接 x -> /path/to/jar/version_1.0.0

现在,我的流程脚本将通过引用符号链接 x 来加载 jar 文件。

现在我的问题是:

在流程仍在运行时... 我可以安全地将符号链接 x 更新为:

符号链接 x -> /path/to/jar/version_1.2.0

我不会删除 /path/to/jar/version_1.0.0,因此它仍将保留在主机上。

我的担忧是,流程可能会开始从新的符号链接路径加载尚未在内存中的 jar 文件,而不是首次运行脚本时从 /path/to/jar/version_1.0.0 路径加载的文件。

英文:

So I am thinking of setting up my deployment scripts for my processes to point to a a symlink which points to the latest version of the jar for my application.

So:

symlink x -> /path/to/jar/version_1.0.0

Now the script for my process will load the jar be referencing symlink x in it's start script.

Now my question is:

Given the process is still running...can I safely update the symlink x to be:

symlink x -> /path/to/jar/version_1.2.0

I won't be removing /path/to/jar/version_1.0.0 so that will still remain on the host.

My concern is that the process may start loading jars that are not in memory yet from the new symlink path rather than the /path/to/jar/version_1.0.0 path the script first ran with.

答案1

得分: 1

当您更新符号链接并加载您的JAR文件时,一切都取决于时间点。
当您创建符号链接时,会分配一个新的inode,这意味着您的符号链接与原始文件是不同的实体。

当您更新(取消链接+重新链接)您的符号链接时,基本上会创建一个新的inode。因此,如果您的第一个符号链接已被调用和使用,新的链接将不会再被使用,除非再次调用。尽管它们具有相同的路径,但它们在文件系统级别上是不同的资源。

英文:

It all depends when you update the symlink and when you load your jar.
When you create a symlink, a new inode is allocated, which means your symlink is a different entity than your original file.

When you update (unlink + link again) your symlink, it basically creates a new inode. So, if your first symlink was already called and used, the new one will not be used anymore, unless is called again. Although they have the same path, they are different resources at the file system level.

答案2

得分: 1

一般来说,我认为您的担忧是正确的。
JVM 在需要时动态加载类。

因此,当进程运行时,可能尚未加载某些类(例如,您可能为非常特定的业务流程“导入”了一些类,但这些类自启动当前运行以来尚未触发)。
因此,如果您改变链接,可能会导致某些功能出现问题。

因此,如果您绝对需要在“无需重启”的情况下提供升级,最好以不同的方式进行:

  • 同时启动两个 JVM:一个将运行旧进程,另一个将运行新进程。
  • 在新版本准备好时开始将流量路由到新版本(好的,这实际上取决于您的应用程序实际执行的操作)。
  • 当您看到它按预期工作时,停止旧应用程序。

现在,这确实取决于您的应用程序的实际情况,您可能需要同步数据库的状态,在同一时间执行两个版本的应用程序的请求等等,因此在一般情况下,这可能是一项相当复杂的任务。

一些现代高级工具(如 Kubernetes)可以在 DevOps 领域提供帮助,但仍然需要理解应用程序的确切情况以实现最佳结果。

英文:

In general, I think your concern is correct.
JVM loads classes dynamically, when they’re really needed.

So its possible that when the process runs some classes are not being loaded yet (say, you “import” some classes for a very specific business flow that has not been triggered yet since the start of the current run).
So if you’ll change the link its possible that some things will break.

So if you absolutely need to provide an upgrade “without restarts” you better do it in a different way:

  • Start two JVMs simultaneously: one will run the old process and one will run the newer process
  • Start when the new version is “ready” start routing the traffic to it (ok, it really depends on what your application really does)
  • When you see it works as expected - stop the old app.

Now this really depends on how does your application really look like, you might need to sync the state of DBs, execute the requests with two versions of the application at the same time, and so forth, so in a general case this can be pretty complicated thing to do.

Some modern advanced tools (like kubernetes) can help in DevOps area here but still you’ll have to understand what exactly happens in the application to achieve the best results.

huangapple
  • 本文由 发表于 2020年8月22日 05:40:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63530388.html
匿名

发表评论

匿名网友

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

确定