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

createh53个月前 (02-01)技术教程30

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基础——面试官:你来说说反射如何获取私有对象的属性和方法

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

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

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

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

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

Java设计模式-单例模式(java单例模式原理)

单例模式定义:它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式主要分为两大类:饿汉式和懒汉式,懒汉式又分为 单线程下的普通懒汉式,多线程下的双重校验锁、静态内部类、枚举。单例模式的...

终于搞懂了 Java 8 的内存结构,再也不纠结方法区和常量池了

java8内存结构图虚拟机内存与本地内存的区别Java虚拟机在执行的时候会把管理的内存分配成不同的区域,这些区域被称为虚拟机内存,同时,对于虚拟机没有直接管理的物理内存,也有一定的利用,这些被利用却不...

java的53个关键字(含2个保留字)第一篇

1.java的关键字(keyword)有多少个? 51+2个保留字=53个关键字(java的关键字都是小写的!!)2.java的保留字(reserve word)有多少个?问题:分别是什么? 1).c...