V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
abcbuzhiming
V2EX  ›  Java

现在 Java 界推崇“use Jar, not War”,但是这 Jar 的内存占用也太。。。。。。

  •  1
     
  •   abcbuzhiming · 2018-12-06 11:33:50 +08:00 · 10087 次点击
    这是一个创建于 2172 天前的主题,其中的信息可能已经有所发展或是发生改变。
    以前我们部署 Java 的 Web 应用,都是搞个 Tomcat 或者 Jetty 这样的 Servlet 容器服务器装到到目标机器,然后每个应用 App 在 Servlet 容器服务器占据一个上下文路径来提供自己的服务。这样的服务器启动时占的内存不大,也就 1GB 左右,但是内部的应用会互相干扰抢占资源占用,有的时候一个应用出现了无法卸载的死机,你会不得不把整个 Servlet 容器服务器停下来。最近的 Java 界,大家都推崇直接用 Jar 包跑,反正 jar 包里有内嵌的 Servlet 容器服务器。好处就是各个 Jar 之间可以互不干扰了,但是这启动内存占用真是吓人,1 个启动的时候都接近 1G 了,一台服务器上启动几个 Jar,内存就要没了。我想了想,这应该还是 Servlet 容器服务器的锅,内嵌的容器服务器那也是服务器啊。所以我想问问各位:
    1.你们这么看待和解决这个问题?
    2.业界最近有干脆去掉 Servlet,用别的方式提供 Web 服务的声音,而且确实出现了这样的框架,有人实践过吗,有好处吗?资源占用情况如何
    44 条回复    2018-12-17 01:51:00 +08:00
    jjianwen68
        1
    jjianwen68  
       2018-12-06 11:44:11 +08:00
    启动占用 1g 不是 jar 本身占用吧,是服务本身加载的 cache 吧
    zjsxwc
        2
    zjsxwc  
       2018-12-06 11:45:13 +08:00
    加 swap 文件分区就行
    sagaxu
        3
    sagaxu  
       2018-12-06 11:48:14 +08:00 via Android
    springboot 内嵌 tomcat 启动,自身占用内存不到 50M,1g 至少能启动 8 个 app。
    lovelybear
        4
    lovelybear  
       2018-12-06 11:48:37 +08:00
    所以还是用 war
    sagaxu
        5
    sagaxu  
       2018-12-06 11:48:42 +08:00 via Android
    @zjsxwc fullgc 遇到 swap 就是找死
    xiaoyunwei2
        6
    xiaoyunwei2  
       2018-12-06 11:52:28 +08:00
    总有人想搞点新花样出来
    misaka19000
        7
    misaka19000  
       2018-12-06 11:54:50 +08:00 via Android   ❤️ 2
    问题在于为什么要在一台负载上面启动多个 jar 进程呢
    abcbuzhiming
        8
    abcbuzhiming  
    OP
       2018-12-06 11:57:32 +08:00
    @jjianwen68 服务本身没有加什么 cache,就是表有点多,50 个表左右,各种 Service,mapper 文件,Controller 也不少
    peyppicp
        9
    peyppicp  
       2018-12-06 11:58:27 +08:00
    Servlet 容器占不了多少资源。对响应没那么高的应用,可以少开点线程。加个-Xmx2g 啥的参数控制一下吧
    jorneyr
        10
    jorneyr  
       2018-12-06 11:58:35 +08:00
    用经典的 Tomcat 部署, 多个 Web 可以把都有的 jar 包放到 Tomcat 的共享 lib 里, 不需要每个应用都各自加载一次这些 jar 包, 这样可以省掉不少资源.
    abcbuzhiming
        11
    abcbuzhiming  
    OP
       2018-12-06 11:58:50 +08:00
    @sagaxu 你的 spring boot 怕不是空项目吧?你加上各种 Controller,Service,Mapper,各种逻辑类,还有 Web 模板,静态资源,然后再看看。
    abcbuzhiming
        12
    abcbuzhiming  
    OP
       2018-12-06 12:01:03 +08:00
    @misaka19000 你一定是在大公司,有海量的服务器给你用,中小型公司哪家服务器上就跑一个 jar 的?
    mmdsun
        13
    mmdsun  
       2018-12-06 12:15:56 +08:00 via Android
    说下是什么命里如何查询 jar 占用内存的?是不是有误差。我这边最多 500M
    boris1993
        14
    boris1993  
       2018-12-06 12:25:33 +08:00 via Android
    @abcbuzhiming #12 裸铁上装 ESXi 啊,然后一个应用开一个虚拟机,资源按需分配,一台虚拟机只跑一个 war 或者 jar
    我司就是这个套路,也没有海量服务器,真铁只有个位数,上面跑了一麻袋虚拟机
    sagaxu
        15
    sagaxu  
       2018-12-06 12:26:48 +08:00 via Android
    @abcbuzhiming 各种 Controller,Service,Mapper,各种逻辑类,还有 Web 模板,静态资源

    这些东西分开也好独立也好,占用的内存是一样多的,没有被共享的,不就是空项目的那部分开销吗?
    tnt666666
        16
    tnt666666  
       2018-12-06 12:29:16 +08:00 via Android
    推崇??去他吗的推崇
    aa6563679
        17
    aa6563679  
       2018-12-06 12:30:32 +08:00 via iPhone
    没那么夸张,一个 jar 服务空闲时 gc 后也就占不到 100m。
    szq8014
        18
    szq8014  
       2018-12-06 12:30:46 +08:00
    @abcbuzhiming 富应用的话 1G 内存不多吧 0。0
    apeshit
        19
    apeshit  
       2018-12-06 12:36:19 +08:00
    遇到这种多个 web services 需要在同一台机器上运行的情况, 为了可靠性和可扩展性, 为什么不使用 kubernetes + docker 的架构? 每个 web service 在自己的容器里面, 可以 configure 每个 service 的资源, replica 和 failover 策略
    abcbuzhiming
        20
    abcbuzhiming  
    OP
       2018-12-06 12:36:56 +08:00
    @mmdsun 我这边是在 windows 发现问题的,windows server 2012R2,任务管理器里,Java Platform SE binary 占用内存 9xx.xxMB。。。
    看了你们说的,我现在也在分析是不是我打开 spring boot 的姿势不太对,这个内存占用貌似有点不太正常的样子
    msg7086
        21
    msg7086  
       2018-12-06 12:49:46 +08:00   ❤️ 3
    @abcbuzhiming #12
    反过来说。没有钱上多台服务器或者高配服务器的,为什么要去用 Java 呢。
    就像以前用 Oracle 的,十年前大家都在说,Oracle 一开,几十 G 内存就没了。那时候 48G 内存的至强都是要有点矿才能买得起了。那所以小公司没人去搞 Oracle 啊。一样的道理。
    Java 的本来设计得就是用大内存换取高性能,买不起内存是你公司的事,你想想不充钱能变强吗(笑)
    passerbytiny
        22
    passerbytiny  
       2018-12-06 13:14:52 +08:00   ❤️ 4
    请善用 Xms、Xmx 参数。如果你的程序小,那么请使用 java -Xms32m -Xmx64m -jar some.jar 来启动。不加参数,5 个 java 进程就能占满内存。
    q397064399
        23
    q397064399  
       2018-12-06 13:21:30 +08:00
    加钱买内存,内存真的很便宜,随便一个程序员的一年的工资 都能买差不多 2T 的服务器内存了。
    买服务器内存的钱都没有,你搞什么 Java?
    Cbdy
        24
    Cbdy  
       2018-12-06 13:23:12 +08:00
    可以不基于 Servlet 做,用 Netty:比如 Vert.x、Spring Web Flux,当然做出来的东西也是 Jar
    bdnet
        25
    bdnet  
       2018-12-06 13:30:08 +08:00
    简单来说,单独一个 JVM 实例隔离型好于共享,各有优缺,脱离场景,没有那个一定好

    不过,现在一个手机内存都 8G 内存了
    HiJackXD
        26
    HiJackXD  
       2018-12-06 13:42:27 +08:00 via iPhone
    可以用用 playframework1.x 之类的不依赖 servlet 容器的框架 速度和开发体验都比 ssm 好多了
    qiyuey
        27
    qiyuey  
       2018-12-06 13:50:35 +08:00
    一台机器只部署一个 Jar,目前主流的方法是 Docker + Jar
    liuxey
        28
    liuxey  
       2018-12-06 14:21:40 +08:00
    我觉得最终云化后就变得像 Google Cloud Function 和 Amazon 的 lambda,不仅把 tomcat 抽象化,servlet 也抽象化,最终面向 Function 编程。

    所以期待 springboot 再次进化,变成一个纯 Serverless 的平台,开发人员面向 Lambda 编程,部署的只是一个一个 lambda,再加入一些可公共调用的 lambda API,完美~
    mmdsun
        29
    mmdsun  
       2018-12-06 18:19:13 +08:00 via Android
    @abcbuzhiming 那算总的。启动 jar 前电脑内存,启动 jar 后电脑内存,两个一减。
    mgcnrx11
        30
    mgcnrx11  
       2018-12-06 18:35:41 +08:00 via iPhone
    Xms 堆参数啊,每个机器内存都不同,这样谈占用有什么意义
    Cbdy
        31
    Cbdy  
       2018-12-06 19:04:08 +08:00 via Android
    @liuxey 已经有了,Spring Cloud Function 了解一下
    http://cloud.spring.io/spring-cloud-function/
    Mohanson
        32
    Mohanson  
       2018-12-06 19:12:52 +08:00
    golang 4000 万请求每日, 常年 20 M 内存, 考虑一下(狗头
    liuxey
        33
    liuxey  
       2018-12-06 19:25:26 +08:00
    @Cbdy #31 这个之前也了解过了,但是还是太粗糙,只是将传统 controller 稍微封装了下,默认 method -> URI 的映射规则,等以后发展看看会变成什么样吧。
    Cellei
        34
    Cellei  
       2018-12-06 20:31:21 +08:00
    抽时间试一下 vert.x
    wdlth
        35
    wdlth  
       2018-12-06 21:20:03 +08:00
    不用 Undertow 么?
    donyee
        36
    donyee  
       2018-12-06 21:36:26 +08:00
    要榨取性能的话,就不推荐使用 java servlet 这些框架;
    1 个应用都不愿意分配 1G 内存,那么是不是你们这些应用功能比较单一、用户量太小
    搞不懂这些...
    loveCoding
        37
    loveCoding  
       2018-12-06 21:36:39 +08:00
    上线前压测下 , 找到合理的-Xms -Xmx ,不要啥都不管直接开始跑
    Vamposine
        38
    Vamposine  
       2018-12-06 21:40:04 +08:00 via iPhone
    @abcbuzhiming 如果是生产环境,一个服务器上就独立放一个 service 才是正解,如果物理服务器个数不够,可以虚拟化,做好资源隔离就好
    TinyKube
        39
    TinyKube  
       2018-12-07 09:21:10 +08:00
    我们这边的微服务模块都慢慢用 go 重写了。云原生时代还是用 Go 吧,Java 的内存占用太夸张了
    xinyewdz
        40
    xinyewdz  
       2018-12-07 10:19:44 +08:00
    使用 jar 启动的,都是使用微服务。每个 jar 提供的服务不多的。你应该是把一个超级大的项目,打包为一个 jar。内存占用肯定大了。
    jlkm2010
        41
    jlkm2010  
       2018-12-07 10:29:18 +08:00
    25 楼正解
    genjigjj
        42
    genjigjj  
       2018-12-07 13:53:24 +08:00
    docker 了解下
    bk201
        43
    bk201  
       2018-12-07 16:08:52 +08:00
    你容器配置中有没限制 jvm 内存占用?而 jar 运行时候限制内存占用了吗?内嵌跑容器,外置也一样跑容器,有什么区别?
    someonedeng
        44
    someonedeng  
       2018-12-17 01:51:00 +08:00 via Android
    1.JVM 参数限制一下堆大小
    2.vert.x
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2514 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 15:57 · PVG 23:57 · LAX 07:57 · JFK 10:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.