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