Ark Serverless初探

Ark Serverless

前几年流行大中台小前台概念,将业务中通用的基础业务服务例如会员、商品、交易等功能服务收敛统一,将这些通用业务合并成一个中台服务,业务前台通过调用中台提供的统一服务实现自己的需求功能。通过业务中台化让业务数据汇总在中台系统,避免以前各个系统的数据隔离,可以实现各业务系统的数据汇总以及沉淀,更好地为前台服务提供支持。

但大中台意味着中台系统的服务接口多、系统庞大,导致需求迭代成本越来越高。系统迭代需要提前很久进行需求规划,将多个团队多个需求变更合并在同一个版本迭代中上线,这导致需求迭代不灵活以及效率低下,并且如果某个迭代需求出现延误无法在预定的版本迭代时间点上线,只能推延到下一个迭代版本上线。

为了解决这个痛点出现了Ark Serverless,通过Ark Serverless可以将一个中台系统拆分成一个Master Biz模块和若干个普通Biz模块。进行需求迭代时只需要负责的团队独立开发迭代上线对应的Biz模块,如同插件一般只对指定的Biz模块进行热部署,大大提高了需求迭代的灵活性,也降低了不同团队之间的协作开发约束。

image

当然这种模式看上去反微服务架构,但随着业务增长系统越来越庞大,全部拆分成微服务会导致应用数量暴增,服务调用链路过长性能下降,另外数量庞大的微服务架构也会造成运维复杂和资源性能浪费的问题。典型的就是与Golang应用做对比,一个相同业务能力的JVM应用动辄需要上G的内存,而Golang只需要区区几十M的内存,相比之下数量庞大的JVM微服务应用会造成资源利用率低问题。

SOFAArk

介绍

SOFAArk是基于JAVA实现的轻量类隔离容器,可以类比外面开源的Tomcat,在容器中可以同时运行多个应用。不过相比Tomcat,SOFAArk除了提供容器运行环境以及运行模块间的类隔离,还提供了运行模块之间的服务交互,允许不同模块之间通过SofaService/SofaReferenceJVM服务进行交互。另外为了模块热插拔的能力,还实现了动态合并部署,SOFAArk对接配置中心,运维可以以此动态控制容器中的模块热部署和卸载。

image

实现

SOFAArk默认为单容器模式,每个Biz模块之间只有classloader隔离,该模式的实现机制见https://www.sofastack.tech/projects/sofa-boot/sofa-ark-classloader/

1
com.alipay.sofa.ark.container.service.classloader.BizClassLoader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Override
protected Class<?> loadClassInternal(String name, boolean resolve) throws ArkLoaderException {
Class<?> clazz = null;
// 0. sun reflect related class throw exception directly
if (classloaderService.isSunReflectClass(name)) {
throw new ArkLoaderException(
String
.format(
"[ArkBiz Loader] %s : can not load class: %s, this class can only be loaded by sun.reflect.DelegatingClassLoader",
bizIdentity, name));
}
// 1. findLoadedClass
if (clazz == null) {
clazz = findLoadedClass(name);
}
// 2. JDK related class
if (clazz == null) {
clazz = resolveJDKClass(name);
}
// 3. Ark Spi class
if (clazz == null) {
clazz = resolveArkClass(name);
}
// 4. pre find class
if (clazz == null) {
clazz = preLoadClass(name);
}
// 5. Plugin Export class
if (clazz == null) {
clazz = resolveExportClass(name);
}
// 6. Biz classpath class
if (clazz == null) {
clazz = resolveLocalClass(name);
}
// 7. Java Agent ClassLoader for agent problem
if (clazz == null) {
clazz = resolveJavaAgentClass(name);
}
// 8. post find class
if (clazz == null) {
clazz = postLoadClass(name);
}
if (clazz != null) {
if (resolve) {
super.resolveClass(clazz);
}
return clazz;
}
throw new ArkLoaderException(String.format("[ArkBiz Loader] %s : can not load class: %s",
bizIdentity, name));
}

image

资源隔离问题

SOFAArk默认所有的Biz运行在同一个容器上,同一个进程内服务调用只需要通过JVM内部通信即可,但也意味着所有的Biz都运行在同一个进程中,物理资源的隔离就成了问题,例如物理机的CPU、磁盘容量等资源无法做到很好的隔离,从而出现因为资源竞争导致的种种问题。

因而SOFAArk为了解决资源隔离的问题,还提供了另一种运行模式:Pod内多容器模式,即每个Biz单独部署在一个容器中,并和基座部署在同一个Pod里。这种模式下每个Biz分配一个进程执行,并且可以实现更加严格的资源隔离,但也因此Biz之间的服务调动无法通过JVM直接通信,需要将JVM服务转成RPC服务来实现服务调用。

image

JVM转RPC方案如下,将mosn作为注册中心,Biz将自己注册到mosn中。如下图,BizB服务调用BizA,在多容器部署模式下,BizA将自己注册到mosn中,BizB通过mosn获取本Pod内可调用的服务端,然后以PRC的形式与BizA进行通信。该方案流程比单容器模式链路更长更复杂,模块间的服务调用通过RPC导致效率不如JVM调用。因此如果不是对资源隔离有严格的要求,建议使用单容器部署模式。

image