从Java转向Go--AeroFS的一段奇妙之旅

createh54周前 (02-01)技术教程18

AeroFS是一家为企业提供安全和廉价的私有云存储方案。日前,AeroFS的开发团队发现程序内存发现异常(AeroFS应用大部分是基于Java开发的),经过排查后发现JVMs之间无法进行更多的只读内存共享,于是决定采用新的开发工具,选用Go语言,随后,代码减半、常驻内存下降、Docker镜像内存也减少许多。AeroFS开发团队将这一事件记录下来,我们一起来看下。

AeroFS应用由很多微服务构成,主要以Java来编写。在一段时间里,它运作良好,服务的用户约为几千。但当我们转到Docker时,发现程序内存占用出现大幅攀升。于是前期我们先是使用了Docker监控工具进行检查,最后得出如下的检测脚本:

for line in `docker ps | awk '{print $1}' | grep -v CONTAINER`; do \

  echo $(( `cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes` / 1024 / 1024 ))MB \

  $(docker ps | grep $line | awk '{printf $NF" "}') ; \

done | sort –n

运行后输出结果是运行中的容器清单,以常驻内存大小进行排序。例如:

  • 46MB web
  • 66MB verification
  • 74MB openid
  • 82MB havre
  • 105MB logcollection
  • 146MB sp
  • 181MB Sparta

该分析没有覆盖那些内存占用异常高的Java服务,因为这是非常规的。我们总结了几点造成内存占用高的因素:

  1. 由于tomcat servlet被放置于单独的容器上,造成JVMs的增加。
  2. JVMs之间无法进行更多的只读内存共享:原因是所有共享库都依赖于JVM本身,以及很多JARs是被多服务所使用的。
  3. 内存分离会导致过多的批量启发,从而使由服务分配的缓存增多。

有鉴于此,我们决定使用新的工具。

代码名字:Greasefire

随后我把该为AeroFS程序减负的项目作为黑客松参赛项目,我的竞赛点是:

  • CPU占用下降
  • 保持内存的稳定和安全
  • 常驻内存占用减少一倍甚至更多

新工具尝试

为了实现CPU和内存的优化目标,选择的语音需要以系统编程为设计根本。经过一番筛选后,Go和Rust成为了我的目标。这两者都能很方便地编译出能在最小型容器运行的小型静态二进制代码,都具有良好的性能表现,安全性以及并发处理支持,最关键的是比JVM有着更少的内存占用。

Rust的类型系统特性非常迷人。但是它与Go相比还是显得稚嫩,同时支持库在HTTP和低阶网络编程上有所欠缺。

与C家族相近的Go入门较易,但是有很多独有的特性需要结合支持文档进行细读。幸好支持文档写得详尽而细致,与标准库资源无缝连接,所以能够使初学者写出清晰可读性高的代码。此外,易于与文本编辑器如vim等整合的gofmt工具的提供,也是很令人兴奋的。

结果

  • 代码缩减了约一半,从175行减少为96行。
  • 常驻内存从87MB下降为3MB,减少了将近29倍。
  • Docker镜像大小从668MB减少为4.3MB。

在黑客马拉松的最后一天,我还对CA(Certificate Authority 认证授权)进行了优化。我们的认证服务先是从内部服务和桌面用户机器上接收证书签名请求,然后以P2P方式在用户和服务器间返回相关签名认证。当我以新CA替换原来的Java时,常驻内存更是减少了100倍。最后,该项目获得了黑客松的技术卓越奖。

原文链接:Aerofs

相关文章

Java:在Java中使用私有接口方法(java私有的)

  接口是定义一组方法及其签名的契约, 它可以由任何类及其在该类中实现的方法进行扩展。从Java9 开始,你可以在接口中使用私有方法。  由于私有方法只能在定义它的接口内访问,因此你可以利用这些方法编...

Python之面向对象:私有属性是掩耳盗铃还是恰到好处

引言声明,今天的文章中没有一行Python代码,更多的是对编程语言设计理念的思考。上一篇文章中介绍了关于Python面向对象封装特性的私有属性的相关内容,提到了Python中关于私有属性的实现是通过“...

Java基础——面试官:你来说说反射如何获取私有对象的属性和方法

最近,@Python大星 的朋友小鹿参加了一场#Java#面试。有一道题是这样的 >>>【面试官问:你来说说反射如何获取私有对象的属性和方法?】问题的答案我们文章中揭晓,先看下反射的...

浅谈Java内省(java内存详解)

作者:京东物流 王国泰一、什么是内省讲内省,不得不说Java Bean,Bean在Java中是一种特殊的类,主要用于装载数据,数据会被存储在类的私有属性中,通常具有无参构造函数、可序列化、以及通过ge...

思考:Java对象之生(java中对象的概念的理解)

内存、性能是程序永恒的话题,实际开发中关于卡顿、OOM也经常是打不完的两只老虎,关于卡顿、OOM的定位方法和工具比较多,这篇文章也不打算赘述了,本章主要是来整理一下JVM的内存模型以及Java对象的生...

java匿名内部类的定义以及使用场景

匿名内部类定义 匿名内部类是Java中一种没有显式声明名称的内部类。它们在创建时被同时声明和实例化,通常用于创建一次性使用的类。它们的特点是:无名称: 无法像普通类一样被其他代码引用。一次性: 通常只...