像 Node,PHP 推代码到服务器就行了,Java 每次打 jar/war 包、停止旧服务、启动新服务,挺麻烦的,从启动到能访问还得等几分钟。
1
NizumaEiji 2019-07-24 09:49:41 +08:00
OSGI?
|
2
laravel 2019-07-24 09:50:40 +08:00
k8s
|
3
gwybiaim 2019-07-24 09:55:34 +08:00 2
有 hotswap 啊
相关的工具也很多,比如阿里巴巴的 arthas https://alibaba.github.io/arthas/index.html http://hengyunabc.github.io/arthas-online-hotswap/ |
4
airfling 2019-07-24 09:55:52 +08:00
这个是是 jvm 的性质导致的,没有好的解决方案,以前有 osgi,但是那个其实也是要很久
|
5
zzf2019 2019-07-24 09:56:21 +08:00
不都是 灰度发布吗?从访问上来说非常平滑呀,这不是 java 的问题吧,node、php 都是只有一个服务吗
|
6
nikandaoleshenme 2019-07-24 09:59:36 +08:00 2
不知道有种工具叫脚本么,
再说了,要不是部署时间间隙这么长,哪有时间来 v 站逛 [搜狗表情] |
7
efaun 2019-07-24 10:00:55 +08:00
分布式是用来干嘛的
|
8
chendy 2019-07-24 10:02:01 +08:00
反向代理 + 脚本
k8s 之类自带滚动升级的东西 |
9
lastpass 2019-07-24 10:02:48 +08:00 via Android
完全可以很简单的热部署呀,我现在就在使用。
在 windows 下编辑和调试代码,自动热部署到另一台 linux 服务器。 |
10
StarkWhite OP @zzf2019 就一台服务器,自己做个人小项目,怎么灰度发布 😂
|
11
ala2008 2019-07-24 10:04:31 +08:00
难道只有一个服务器?
|
12
StarkWhite OP @cshijiel 感谢分享。但是在 arthas 官网的说明里没有热部署啊。hotswap 我再看看
|
13
liangkang1436 2019-07-24 10:06:31 +08:00
推荐 Jrebel
https://jrebel.com/ |
14
gwybiaim 2019-07-24 10:06:57 +08:00
@StarkWhite 看第二个链接,三个命令就可以。最关键的是 redefine 命令,参考 https://alibaba.github.io/arthas/redefine.html
|
15
guokeke 2019-07-24 10:07:55 +08:00 via Android
单机可以用 nginx 反代多个 server 那样搞
|
16
Xbluer 2019-07-24 10:08:14 +08:00 via iPhone
@StarkWhite 问题就变成了,个人小项目直接重启一下又不会太久,上啥热部署啊
|
17
StarkWhite OP @laravel k8s 那一套太重了,还不如手动部署。。。
|
18
Caballarii 2019-07-24 10:09:48 +08:00
java 从来不止起一个服务,停一个切路由起完了再切回来就好了
|
19
StarkWhite OP @lastpass 你怎么实现的呢?
|
20
jowan 2019-07-24 10:11:44 +08:00
PHP 也得看你是什么业务
像我们的光推代码是不行的 还得重启队列,Socket 等服务 |
21
StarkWhite OP |
22
StarkWhite OP @liangkang1436 感谢,但是 jrebel 官网打不开,蜜汁尴尬
|
23
lastpass 2019-07-24 10:16:07 +08:00 via Android
@StarkWhite #19 依靠 idea 和 jvm 的支持呀。首先 ssh 连接到远程服务器,配置 remote tomcat。tomcat 配置 jmx remote 开启远程调试。最后 idea 配置 automatic upload 以推送资源文件。
|
24
lihongjie0209 2019-07-24 10:16:29 +08:00 2
类似这种问题, 你可以问一下 windows 团队为什么更新需要重启
|
25
notreami 2019-07-24 10:18:36 +08:00
类比 Node,PHP 的话,springboot 的 devtools 就可以了,监听某个目录下的文件,有变化就重新加载运行。
稳定点的话,使用模块化方式,比如 osgi、Jigsaw、Guice 等等,但是这些都太麻烦,对开发方式影响太大。 |
26
crayhuang 2019-07-24 10:33:35 +08:00
jrebel+1
|
27
szq8014 2019-07-24 10:37:07 +08:00
想直接发布代码也没人有阻止呀~比如 maven 项目,就可以直接在服务器更新代码然后再 package 再 run。 [此处需要加狗头]
|
28
redford42 2019-07-24 10:37:25 +08:00 5
不然 Java 图标为什么是一杯咖啡呢
|
29
Raymon111111 2019-07-24 10:47:02 +08:00
答案是 是
没有简便的解决方案 jvm 特性导致的 |
30
rockyou12 2019-07-24 10:52:07 +08:00
单机 java 又是个人项目最好就别搞灰度了,费力不讨好。用 nginx 其实也不算简单,要你本地新旧两个服务用不同端口,然后 upstream。
k8s 的 deployment 发布已经是最省事的灰度发布了,如果机器不够真的不如不做 |
31
Infernalzero 2019-07-24 10:57:43 +08:00 1
楼上也很多人说了,这个没有彻底的解决方案,jvm 特性导致
只能是想办法减少启动时间,这里主要分两块,一块是 JIT 导致的,只能像阿里那样从 jvm 层面去改 还有一块是 spring 导致的,因为 spring 的依赖注入,创建 bean 和扫描非常耗时,所以使得 java 应用启动更慢,这个目前业界的思路是把依赖注入放到编译构建阶段去做,对应的框架是 micronaut,但是这个要取代 spring 有点困难。 |
32
qiyuey 2019-07-24 11:04:54 +08:00
热部署一定是需要的吗?
|
33
passerbytiny 2019-07-24 11:10:03 +08:00
“类似这种问题, 你可以问一下 windows 团队为什么更新需要重启” —— lihongjie0209
纵观楼主的回复,还是这个最接近答案,其他人可以散了。 |
34
fivesmallq 2019-07-24 11:10:46 +08:00
你可以试试 play 1.x https://www.playframework.com/documentation/1.5.x/home
支持热部署,springboot 的 devtools 太 low 了,实际上还是重启。 不过这个特性不建议生产环境使用 |
35
Takamine 2019-07-24 11:25:17 +08:00
devtools。
|
36
mineqiqi 2019-07-24 11:32:58 +08:00
分布式的项目可以平滑过渡升级,但是并不是热部署
|
37
StarkWhite OP @redford42 意思应该先自己冲一杯咖啡,然后在慢慢喝,喝完了可以瞄一眼进度?/滑稽
|
38
StarkWhite OP @mineqiqi 没钱啊,个人小项目上分布式,得买几台服务器,而且运维麻烦
|
39
luckyrayyy 2019-07-24 11:42:56 +08:00
nginx or docker
|
40
lihongjie0209 2019-07-24 11:44:02 +08:00
@StarkWhite #38 没必要上分布式, 只用多节点就可以了. 一台服务器部署两个一样的应用, 监听不同的端口, nginx 做负载就好了
|
41
est 2019-07-24 11:48:52 +08:00
node 那个不叫热部署吧。。。
严格的说文件拷贝过程中出了什么差错还会出问题的。 |
42
th00000 2019-07-24 12:01:30 +08:00
现在部署都是集群内的 rolling update, 楼主的热部署指的是在同一个服务不停的情况下, 直接推送更新吧, 在当前的集群环境下, 个人认为必要性越来越低.
但是开发的时候爽啊 不用改一行代码就重启了, 直接 reload 完事. |
43
ninjachen 2019-07-24 12:06:26 +08:00
对的,nginx 那边做个路由,然后反向代理到多个 port,也就是多个 java 实例
|
44
Weixiao0725 2019-07-24 12:38:46 +08:00
从根本上来说,java 是做不到热更新的,因为 Java 中只要 jar 包中的文件被载入到内存后,就不支持删除。像 Tomcat 那种热部署,无非也就是把所有的数据结构重新载入一遍。
|
45
akira 2019-07-24 12:59:53 +08:00
热不热不重要,只要能"快速"
|
46
StarkWhite OP @qiyuey 能省很多时间啊
|
47
StarkWhite OP |
48
StarkWhite OP @akira 也是,就是想省事儿~ 如果有别的类似热更新、热加载之类方式的也行啊
|
49
pursuer 2019-07-24 14:34:52 +08:00 via Android
@Weixiao0725 classloader 是可以从内存卸载 jar 包的,只是如果不清除外部引用的话不会被 gc 清理
|
50
StarkWhite OP @jowan 也是,这个又引申出来状态丢失问题。所有重启服务的方式,都会导致缓存丢失。。。
|
51
StarkWhite OP @th00000 对的,但我就一台服务器啊,搞不了集群
|
52
StarkWhite OP @est 文件都拷贝出差错了,那用什么方式都会有问题吧 😂
|
53
gwybiaim 2019-07-24 14:46:45 +08:00
@StarkWhite 没错,redefine 有很多约束
|
54
wr410 2019-07-24 14:46:50 +08:00
与其想办法怎么弄热部署,不如想办法从前端做多机均衡,如果你关闭指令发出之后,还有线程没跑完连接没断开,这时候你就知道前端均衡的好处了。
|
55
yuankui 2019-07-24 14:50:13 +08:00
需要一套新轮子,楼主等我消息 😆
|
56
freexyxyz 2019-07-24 14:51:27 +08:00
用 Jenkins 之类的工具,配个流水线就行了……
|
57
est 2019-07-24 14:57:31 +08:00
|
58
StarkWhite OP @cshijiel hotswap 限制太大了,基本没法用啊,除了修复小 bug。。。
“只允许修改方法体,不允许增加新的 class、不允许新增字段、不允许新增方法、不允许修改方法签名” |
59
cominghome 2019-07-24 15:00:12 +08:00
事实上有成熟的流水线的话,热更新听起来就像一个伪需求
|
60
StarkWhite OP @yuankui 期待,到时候记得通知我哈
|
61
StarkWhite OP @fivesmallq
例子挺全的,但一看核心库居然只有 10 多个类。 原来我以为它基于 Spring,怎么看都不像,用它岂不是得还框架了。。。 https://github.com/playframework/playframework/tree/master/core/play-java/src/main/java/play |
62
yuankui 2019-07-24 15:08:15 +08:00 1
我们之前,有个 spring 应用,启动很慢,我专门统计了下每个 bean 的初始化时间长。后来发现主要是以下几类:
- 那些需要远程连接服务进行初始化的,比如 RPC 连接初始化 - 那些需要加载大量数据到内存中的(比如建立一个字典) 所以,要想应用实现热加载,关键是让应用无状态,这就是 php 的主要是方式。 另外一个就是状态向后兼容,比如之前内存保存在一个对象 class A(a,b,c),后面加了个字段 class A'(a,b,c,d),目前 jvm 里面还没有工具支持,将这种数据 A 对象升级成 A'对象,但是实际上,让人来做,是可以做的。js 是可以的,因为 js 运行时全是 object ( kv ),天然具有向后兼任性。所以即使 js 应用,有状态,数据还是能做到兼容,不需要重启。 所以综上,主要是问题其实不是 Java 的问题,而是框架的问题,也就是 spring 的问题。(楼上不是有人说 play 支持热加载吗?我没具体看啥原理哈) 可能目前这个还不是痛点,就是大家遇到了,也是尽量先不启动应用进行开发,而是进行“单元开发”=》“单元测试” 等差不多了, 在起应用,然后这个时候,即使有小 bug,也可以利用 IDE 的动态加载,将 body 体里面的实现替换,这个是不需要重启的。 |
63
arrow8899 2019-07-24 15:31:28 +08:00
拆分服务,减小部署包大小;
减少不必要的依赖,加快启动速度; 无状态; 分布式负载均衡,滚动升级。 |
64
StarkWhite OP @yuankui 赞,感谢分享。网上看到说 Play 也是基于 hotswap 的原理,看起来也会有 #58 楼 hotswap 的各种不支持的问题。
|
65
StarkWhite OP @cominghome 个人小项目也整个流水线?真是袁隆平的锅 /狗头
|
66
kaneg 2019-07-24 15:37:37 +08:00 via iPhone
JSP 可以解决你的问题
|
67
StarkWhite OP @kaneg JSP 这种古董技术都要淘汰了。。。现在都是前后端分离
|
68
freexyxyz 2019-07-24 15:58:32 +08:00
@StarkWhite 你想实现 “提交代码……然后服务器自动更新好” 用 CI/CD 工具就行……流水线就是 devops 里的一个叫法,可以玩的很高级,也可以往简单了玩……你配个持续部署出来就行了
|
69
StarkWhite OP @freexyxyz 在公司也用 Jenkins,自己业务搞个小项目也用它不划算啊
|
70
StarkWhite OP @StarkWhite 业余
|
71
StarkWhite OP @rockyou12 是啊,费力不讨好。
低配 ECS 云服务器,Nginx 重载配置到生效也得好几分钟 /囧 |
72
StarkWhite OP @efaun 目前在做个人小项目,单机、单体服务,搞分布式运维麻烦,还要钱啊
|
73
StarkWhite OP @Xbluer 不止是重启,还要打包,上传。。。
|
74
efaun 2019-07-24 17:21:40 +08:00
@StarkWhite #70 低成本解决的话就弄定时任务,找个深夜无人的时候自动化发布
|
75
yiyi11 2019-07-24 17:43:32 +08:00 1
如果你要的是只是效率,而不是真正的不停机更新,那么可以试下这个:
https://help.aliyun.com/document_detail/108590.html?spm=a2c4g.11174283.3.5.1813190cmVAJlX Alibaba Cloud Toolkit idea 插件 配置服务器的地址,一键打包,上传,部署 springboot 应用。 |
76
StarkWhite OP @efaun 唉,项目太小弄定时任务不划算
|
77
StarkWhite OP @Takamine 楼上(#34 )说 devtools 太 low 了,实际上还是重启。这不是我想要的效果。。。
|
78
wowo243 2019-07-24 18:37:16 +08:00 via Android
jrebel 应该是最好的了,但是个人认为依然不够好
|
79
momocraft 2019-07-24 18:44:31 +08:00
我觉得至少要保证版本变更是原子的吧
所谓 “ PHP 支持热加载” 听上去像面向巧合运营 |
80
Xbluer 2019-07-24 18:48:42 +08:00 via iPhone
@StarkWhite maven 负责编译测试打包,scp 上传,,ssh 远程命令重启。以上用一个脚本封装一下完全没问题。
|
81
StarkWhite OP @wowo243 它有啥问题呢?
|
82
billlee 2019-07-24 22:05:24 +08:00
@StarkWhite #51 一台服务器也可以搞集群,你在一台机器上起两个服务就可以了
|
83
okwork 2019-07-24 22:18:30 +08:00
楼主服务器配置了多少内存?
用过一个 4G 内存的机器,项目一启 2G 就没了,后来加到 8G 搞 2 个端口,勉强实现灰度。 |
84
oneisall8955 2019-07-24 22:45:37 +08:00 via Android 1
我说下这个情况,让我想起之前几个月的坑。
1.tomcat 有 autodeploy 选项,直接打 war 包到 webapps 下,会自动解压更新项目。但是都是会停掉服务对应的项目重新开启,也就是说虽然 tomcat pid 不变,但是项目还是停掉在开。况且这个热部署有个坑,就是热部署太多次会导致 Compressed class 满了从而 oom 异常了。(这个空间默认 1G,每次看你 class 总内存多少,除一下就知道多少次就回报异常了) 所以这个选项对于楼主没用 2.jrebel 对于开发环境很有用,但有时候还抽风会不生效。这个是 jvm 的一个插件,开发环境我信赖他可以帮助我节约时间,避免多次重启服务器浪费时间。但是对于生产环境,我并不需要每时每刻去实时修改,而是在开发时候,通过频繁修改本地代码实时更新校验修改是否正确,最后再更新到服务器上。况且这个插件还是收费的,你在生产环境里面部署,破解了,被商业检测出来会不会存在什么问题?况且有时候本地调试还会失效,万一生产上面抽风失效了呢?但是自己的小项目,可以尝试这种方式。 3.问题关键是楼主的单体应用里面。假如是 nginx 配置服务集群均衡,配合上 CI 工具写个脚本一个 tomcat 重启更新就很难自己感受到重启这件事了。还节省自己打包,上传,移动到 webapps 这个步骤,除了实际上是要重启服务器这个操作,基本能满足楼主的要求了吧。 愚见,并没有实际解决楼主问题,以上均自己工作经验一点分享。 |
85
q397064399 2019-07-24 22:57:03 +08:00
Java 重启太耗时,主要是 bean 的装配,这种工作本来应该放到编译时做的,但是为了更好的解耦,目前 Spring 依赖注入这套玩法灵活性很高,把很多编译时可以做的事情,都放到了运行时,有些 Bean 检查网络连接之类的,反正整个装配阶段是极其耗时的
另外 Jvm 的特性我不是很清楚, 另外热更新的这种事情最好不要做,序列化 /反序列化 会产生很多问题,有些小公司的项目本来就混乱,DB 的 model 类又不做版本管理,我至少吃过好几次序列化的亏,这还不是热更新,考虑到热更新 会出更多问题,没有良好的版本管理跟发布流程 建议不要做这种费力不讨好的事情,现在微服务大行其道,就是要利用小服务 这种加载 运行 速度快的特性,即使出问题 可以通过灰度 等方法来解决。 |
87
Weixiao0725 2019-07-25 09:02:10 +08:00
@pursuer 请问有相关的资料吗?如果 java 支持内存删除的话,我想那些打桩工具不需要只在启动的时候注入,任何程序运行的时候都可以重新卸载某个类然后再读入字节码,编辑和载入。
|
88
StarkWhite OP @billlee 用不同的端口吗?
|
89
StarkWhite OP @okwork 最低配的阿里云 ECS,1 核 1GHz,1G 内存,40G 云盘。。。
|
90
StarkWhite OP @oneisall8955 感谢分享,打这么多字,辛苦了哈
|
91
pursuer 2019-07-25 10:34:30 +08:00 via Android
@Weixiao0725
直接看 classloader 的 api 文档就可以 加载卸载还是要以 classloader 为单位的。没有引用的 classloader,System.gc 就清理了,只是要保证没有引用很困难,要求工程的模块化做的很好。 |
92
StarkWhite OP |
93
wangxiaoaer 2019-07-25 10:48:29 +08:00
我们一般开个新端口启动一个新的应用,nginx 指向新应用,重启 nginx,停止老应用。
|
94
StarkWhite OP @wangxiaoaer 我那个垃圾服务器重启 nginx 得几分钟才能让配置生效。。。
|
95
fivesmallq 2019-07-25 11:06:55 +08:00
@StarkWhite https://github.com/playframework/play1 你看错了,你看的那个是 2.x 的,用 scala 重写的,1.x 的才是主要用 java 的。
|
96
StarkWhite OP @fivesmallq 这样啊,感谢,我再瞅瞅
|
97
StarkWhite OP @fivesmallq 这个代码量就正常了,像是一个 HTTP Server 框架该有的,哈哈
|
98
fivesmallq 2019-07-25 11:26:20 +08:00
@StarkWhite 对的,你跑下 demo,会喜欢的,适合中小型项目
|
99
StarkWhite OP @fivesmallq 感谢,我试试。现在已经用 SpringBoot 开发了一些接口了。
如果 Play 确实好用,而且迁移成本不高的话,可以迁过去看看。 |
100
StarkWhite OP @StarkWhite 话说这个框架有么有什么大的坑呢?
|