阿里的Pandora Boot的核心是Pandora,因此在介绍Pandora Boot之前需要先介绍Pandora。在阿里集体内部,几乎所有的应用都用到了各式各样的中间件,比如HSF、TDDL、Diamond等等。本身中间件之间可能就有版本依赖的问题,比如你的应用HSF和Diamond分别依赖了同名jar包的不同版本,maven只会引入其中一个版本。同样的中间件和应用之间也存在同样的Jar包依赖的问题,出于要解决这些依赖冲突的问题,阿里就开发了Pandora。简单的来说就是一个类隔离容器,对外以taobao-hsf.sar这样的sar包的形式对外呈现。
一、Alibaba-pandora boot背景Pandora主要解决的问题就是依赖冲突问题,在阿里集体内部,几乎所有的应用都用到了各式各样的中间件,比如HSF、TDDL、Diamond等等。本身中间件之间可能就有版本依赖的问题。例如:
- 二方包、三方包冲突: 由于版本不一致可能导致应用起不来。
- 冲突排查浪费大量时间:应用起不来的时候可能只是应用开发自己折腾半天在排包,但如果是二方包冲突,那么中间件团队可能就要花大量时间在答疑上面,和应用开发一起折腾了。
- 应用难以保持稳定:折腾半天应用终于跑起来了,但是更可怕的就是现在能跑,到了某个点某个场景可能就出bug了。
- 中间件升级困难:如果要实时升级中间件到推荐版本,但是发现并没有那么容易,应用中引入了十个八个中间件,隔三差五其中一个中间件就有小版本更新,每天盯着中间件的更新情况,那还有时间关心业务的开发了。
- 实现类隔离,提供稳定的运行环境:Pandora实现了应用与中间件之间隔离、中间件与中间件之间隔离,保证了类的正确加载,而不会让依赖关系与依赖加载出现不一一对应的情况。
- 中间件平滑升级:由于应用服务器会优先加载Pandora的类,因此只要升级Pandora中的插件即可,无需对应用中的pom.xml进行修改。只需要在aone上面提交一个“HSF变更”即可。
- 中间件统一管理:Pandora会统一管理中间的启动、初始化以及资源回收等一系列操作。
PandoraBoot是在Pandora的基础之上,发展处的更轻量使用集团中间件的方式;它基于Pandora和Fat Jar基础,可以可以在IDE里启动Pandora环境,开发调试等效率大大提高。也就是PandoraBoot是Pandora与Spring Boot结合的产物,可以方便的享受Spring Boot社区带来的便利。
2.1 PandoraBoot与SpringBoot的联系和区别两者联系:
- PandoraBoot是运行中在SpringBoot上的,完全兼容。对PandoraBoot来说SpringBoot就像是一个依赖或者简单的Main函数应用。
两者区别:
- Spring Boot 通过 Maven 来管理依赖,是平板化的,最前面提到的二方包、三方包依赖问题,SpringBoot解决不了。
- Pandora Boot很好的管理了中间件应用,用户可以快速的引入各类中间件,平滑的保持中间件升级。这两者说到底也就是集成了 Pandora 的类隔离技术。
- Pandora Boot 目前很好的集成了 autoconfig,外部也和 AONE2、PSP 等系统进行打通,开发起来更加的方便。
开发者可以在本地使用轻量级配置及注册中心实现应用的注册、发现和配置管理,完成应用的开发和测试。在将应用部署到EDAS后,这些功能仍然可以正常使用。
不同的系统下载不同的版本
- Windows:
- 下载轻量级配置及注册中心压缩包。
- 在本地解压压缩包。
- Unix/macOS:
- 执行命令
wget http://edas.oss-cn-hangzhou.aliyuncs.com/edas-res/edas-lightweight-server-1.0.0.tar.gz
下载轻量级配置及注册中心压缩包。 - 执行命令
tar -zvxf edas-lightweight-server-1.0.0.tar.gz
解压压缩包。
启动轻量级配置及注册中心
- Windows:
- 进入目录
edas-lightweight\bin
。 - 启动轻量级配置及注册中心,并查看启动结果。
- Windows:双击
startup.bat
。
- Unix/macOS
- Unix/macOS:执行
sh startup.sh
。
/usr/java/jdk1.8.0/bin/java -server -Xms1g -Xmx1g -Xmn512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/root/service/edas-lightweight/logs/java_heapdump.hprof -XX:-UseLargePages -Djava.ext.dirs=/usr/java/jdk1.8.0/jre/lib/ext:/usr/java/jdk1.8.0/lib/ext:/root/service/edas-lightweight/plugins/cmdb:/root/service/edas-lightweight/plugins/mysql -Xloggc:/root/service/edas-lightweight/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/root/service/edas-lightweight -Dnacos.standalone=true -jar /root/service/edas-lightweight/target/edas-lightweight.jar --spring.config.location=classpath:/,classpath :/config/,file:./,file:./config/,file:/root/service/edas-lightweight/conf/ --logging.config=/root/service/edas-lightweight/conf/nacos-logback.xml --server.max-http-header-size=524288
2. edas lightweight is starting with standalone
3. edas lightweight is starting,you can check the /root/edas-lightweight/logs/start.out
检查轻量级配置及注册中心的启动监听端口。正常启动后,会在本节点上监听以下三个端口:
- 8848:用来支持基于Nacos应用的配置管理及服务注册。
- 9600:HSF/Dubbo的服务注册及订阅。
- 8080:支持ANS的服务注册以及ACM的配置管理。
Linux/macOS操作系统环境,可使用netstat -an | grep -E "8080|8848|9600" | grep -i listen
命令查看上述三个端口是否处在监听状态(Linux操作系统还可以使用netstat -nltp | grep -E "8080|8848|9600"
来检查这三个端口的打开情况以及是否是轻量级配置及注册中心的进程打开的)。
在本地开发环境中配置hosts
在需要使用轻量级配置及注册中心开发、测试应用的机器上配置轻量级配置及注册中心的hosts,即在DNS(hosts文件)中将jmenv.tbsite.net
域名指向启动了轻量级配置及注册中心的机器IP。
- 打开hosts文件。
- Windows操作系统:C:\Windows\System32\drivers\etc\hosts。
- Unix/macOS操作系统:/etc/hosts。
- 添加轻量级配置及注册中心配置。
- 如果在IP为192.168.1.100的机器上启动了轻量级配置及注册中心,则需要在hosts文件里加入配置:
192.168.1.100 jmenv.tbsite.net
。 - 如果在本地启动轻量级配置及注册中心,则在hosts文件中配置将上面的IP改为
127.0.0.1 jmenv.tbsite.net
。
- 如果在IP为192.168.1.100的机器上启动了轻量级配置及注册中心,则需要在hosts文件里加入配置:
注册与发现配置环境测试
- 本机
在浏览器中输入轻量级配置及注册中心地址
http://127.0.0.1:8080
并回车。 - 独立机器
在浏览器中输入轻量级配置及注册中心地址
http://机器 IP 地址:8080
并回车。
如果首页不能正常显示,可以查看安装目录下的启动日志文件logs/start.log
定位启动失败的原因,并修复。
目前Spring Cloud for Aliware的第三方包只发布在EDAS的私服中,所以需要在Maven中配置EDAS的私服地址。本地开发调试时,需要启动轻量级配置注册中心。轻量级配置及注册中心包含了服务发现和配置管理功能。
在Maven中配置EDAS的私服地址
/root/.m2/repository
alimaven
central
aliyun maven
http://maven.aliyun.com/nexus/content/repositories/central/
mirrorId
repositoryId
Human Readable Name for this Mirror.
http://my.repository.com/repo/path
nexus
central
http://repo1.maven.org/maven2
true
true
central
http://repo1.maven.org/maven2
true
true
edas.oss.repo
edas-oss-central
taobao mirror central
http://edas-public.oss-cn-hangzhou.aliyuncs.com/repository
true
true
edas-oss-plugin-central
http://edas-public.oss-cn-hangzhou.aliyuncs.com/repository
true
true
nexus
edas.oss.repo
测试Maven中配置EDAS的私服地址
在命令行执行命令mvn help:effective-settings,验证配置是否成功。无报错,表明 setting.xml 文件格式没问题。profiles 中包含 edas.oss.repo 这个 profile,表明私服已经配置到 profiles 中。在 activeProfiles 中 包含 edas.oss.repo 属性,表明 edas.oss.repo 私服已激活。说明:如果在命令行执行 Maven 打包命令无问题,IDE 仍无法下载依赖,请关闭 IDE 重新打开试试,或自行查找 IDE 配置 Maven 的相关资料。
mvn help:effective-settings
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.080 s
[INFO] Finished at: 2019-03-05T15:07:23+08:00
[INFO] ------------------------------------------------------------------------
在命令行执行如下命令 mvn help:effective-settings 。可能会报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-help-
plugin:3.1.1:effective-settings (default-cli) on project standalone-pom:
Execution default-cli of goal org.apache.maven.plugins:maven-help-
plugin:3.1.1:effective-settings failed: Plugin org.apache.maven.plugins:maven-
help-plugin:3.1.1 or one of its dependencies could not be resolved: Could not
find artifact org.sonatype.aether:aether-impl:jar:1.7 in edas-oss-plugin-central
(http://edas-public.oss-cn-hangzhou.aliyuncs.com/repository) -> [Help 1]
IDEA中配置的maven环境
SpringPrinciple: SpringPrinciple
或者下载源码:https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/microservice-doc-demo/hsf-pandora-boot?spm=a2c4g.11186623.0.0.6beb7062jEQ0Ew
hsf-pandora-boot-provider的Maven工程
1.8
2.1.6.RELEASE
2019-06-stable
com.alibaba.boot
pandora-hsf-spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
com.taobao.pandora
pandora-boot-starter-bom
${pandora-boot.version}
pom
import
org.apache.maven.plugins
maven-compiler-plugin
3.7.0
1.8
1.8
com.taobao.pandora
pandora-boot-maven-plugin
2.1.11.8
package
repackage
虽然HSF服务框架并不依赖于Web环境,但是在应用的生命周期过程中需要使用到Web相关的特性,所以需要添加spring-boot-starter-web
的依赖。
pandora-hsf-spring-boot-starter
实现了HSF配置的自动装配。pandora-boot-maven-plugin
是Pandora Boot提供的Maven打包插件,可以将Pandora Boot HSF工程编译为可执行的FatJar,并在EDAS Container中部署运行。
dependencyManagement
中包含了spring-boot-dependencies
和pandora-boot-starter-bom
两个依赖,分别负责Spring Boot和Pandora Boot相关依赖的版本管理,设置之后,您的工程无需将parent设置为spring-boot-starter-parent
。
定义服务接口,创建一个接口类com.alibaba.edas.HelloService
。
HSF服务框架基于接口进行服务通信,当接口定义好之后,生产者将通过该接口实现具体的服务并发布,消费者也是基于此接口去订阅和消费服务。
public interface HelloService {
String echo(String string);
}
接口com.alibaba.edas.HelloService提供了echo方法。
添加服务提供者的具体实现类EchoServiceImpl,并通过注解方式发布服务。
@HSFProvider(serviceInterface = HelloService.class, serviceVersion = "1.0.0")
public class HelloServiceImpl implements HelloService {
@Override
public String echo(String string) {
return string;
}
}
在HSF应用中,接口名和服务版本才能唯一确定一个服务,所以在注解HSFProvider中的需要添加接口名com.alibaba.edas.HelloService和服务版本1.0.0
。
说明
- 注解中的配置拥有高优先级。
- 如果在注解中没有配置,服务发布时会优先在resources/application.properties文件中查找这些属性的全局配置。
- 如果注解和resources/application.properties文件中都没有配置,则会使用注解中的默认值。
spring.application.name=hsf-pandora-boot-provider
server.port=8081
spring.hsf.version=1.0.0
spring.hsf.timeout=3000
说明 建议将服务版本(spring.hsf.version
)和服务超时(spring.hsf.timeout
)都统一配置在application.properties中。
添加服务启动的main函数入口
@SpringBootApplication
public class HSFProviderApplication {
public static void main(String[] args) {
// 启动Pandora Boot用于加载Pandora容器。PandoraBootstrap.run(args);
SpringApplication.run(HSFProviderApplication.class, args);
// 标记服务启动完成,并设置线程wait。防止业务代码运行完毕退出后,导致容器退出。PandoraBootstrap.markStartupAndWait();
}
}
服务提供者属性列表
属性是否必配描述类型默认值serviceInterface是服务对外提供的接口Classjava.lang.ObjectserviceVersion否服务的版本号String1.0.0.DAILYserviceGroup否服务的组名StringHSFclientTimeout否该配置对接口中的所有方法生效,但是如果客户端通过methodSpecials属性对某方法配置了超时时间,则该方法的超时时间以客户端配置为准。其他方法不受影响,还是以服务端配置为准(单位ms)int-1corePoolSize否单独针对这个服务设置最小活跃线程数,从公用线程池中划分出来int0maxPoolSize否单独针对这个服务设置最大活跃线程数,从公用线程池中划分出来int0delayedPublish否是否延迟发布booleanfalseincludeFilters否用户可选的自定义过滤器String[]空enableTXC否是否开启分布式事务GTSbooleanfalseserializeType否服务接口序列化类型,hessian或者javaStringhessiansupportAsynCall否是否支持异步调用Stringfalse
服务创建及发布限制
名称示例限制大小是否可调整{服务名}:{版本号}com.alibaba.edas.testcase.api.TestCase:1.0.0最大192字节否组名aliware最大32字节否一个Pandora应用实例发布的服务数N/A最大800个是,可在左侧导航栏单击基本信息在基本信息页签内的应用设置区域内,单击JMV参数右侧的编辑,然后在弹出的应用设置对话框中选择自定义 > 自定义参数,在输入框中添加-DCC.pubCountMax=1200
属性参数(该参数值可根据应用实际发布的服务数调整)
hsf-pandora-boot-consumerr的Maven工程
1.8
2.1.6.RELEASE
2019-06-stable
com.alibaba.boot
pandora-hsf-spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
com.taobao.pandora
pandora-boot-starter-bom
${pandora-boot.version}
pom
import
org.apache.maven.plugins
maven-compiler-plugin
3.7.0
1.8
1.8
com.taobao.pandora
pandora-boot-maven-plugin
2.1.11.8
package
repackage
将服务提供者所发布的API服务接口(包括包名)拷贝到本地,如com.alibaba.edas.HelloService。
public interface HelloService {
String echo(String string);
}
通过注解的方式将服务消费者的实例注入到Spring的Context中。
@Configuration
public class HsfConfig {
@HSFConsumer(clientTimeout = 3000, serviceVersion = "1.0.0")
private HelloService helloService;
}
说明 在HsfConfig
类里配置一次@HSFConsumer
,然后在多处通过@Autowired
注入使用。通常一个@HSFConsumer
需要在多个地方使用,但并不需要在每次使用的地方都用@HSFConsumer
来标记。只需要写一个统一的HsfConfig
类,然后在其它需要使用的地方,直接通过@Autowired
注入即可。
为了便于测试,使用SimpleController来暴露一个/hsf-echo/*的HTTP接口,/hsf-echo/*接口内部实现调用了HSF服务提供者。
@RestController
public class SimpleController {
@Autowired
private HelloService helloService;
@RequestMapping(value = "/hsf-echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return helloService.echo(str);
}
}
在resources目录下的application.properties文件中配置应用名与监听端口号
spring.application.name=hsf-pandora-boot-consumer
server.port=8080
spring.hsf.version=1.0.0
spring.hsf.timeout=1000
添加服务启动的main函数入口
@SpringBootApplication
public class HSFConsumerApplication {
public static void main(String[] args) {
PandoraBootstrap.run(args);
SpringApplication.run(HSFConsumerApplication.class, args);
PandoraBootstrap.markStartupAndWait();
}
}
服务消费者属性列表
属性是否必配描述类型默认值serviceGroup否服务的组名StringHSFserviceVersion否服务的版本号String1.0.0.DAILYclientTimeout否客户端统一设置接口中所有方法的超时时间(单位ms)int-1generic否是否支持泛化调用booleanfalseaddressWaitTime否同步等待服务注册中心( ConfigServer )推送服务提供者地址的时间(单位ms)int3000proxyStyle否代理方式(JDK或Javassist)StringjdkfutureMethods否设置调用此服务时需要采用异步调用的方法名列表以及异步调用的方式,默认为空,即所有方法都采用同步调用String[]空consistent否负载均衡是否使用一致性哈希String空methodSpecials否配置方法级的超时时间、重试次数、方法名称com.alibaba.boot.hsf.annotation.HSFConsumer.ConsumerMethodSpecial[]空
服务提供者和消费者全局配置参数列表
属性是否必配描述类型默认值spring.hsf.version否服务的全局版本号,还可以使用spring.hsf.versions.=
,例如spring.hsf.versions.com.aliware.edas.EchoService="1.0.0"
为具体某个服务设置版本号。String1.0.0.DAILYspring.hsf.group否服务的全局组名,还可以使用spring.hsf.groups.=
为具体某个服务设置组名。StringHSFspring.hsf.timeout否服务的全局超时时间,还可以使用spring.hsf.timeouts.=
为具体某个服务设置超时时间。Integer无spring.hsf.max-wait-address-time否同步等待服务注册中心( ConfigServer )推送服务提供者地址的全局时间(单位ms ),还可以使用spring.hsf.max-wait-address-times.=
为具体某个服务设置的等待服务注册中心(ConfigServer)推送服务提供者地址的时间。Integer3000spring.hsf.delay-publish否服务延迟发布的全局开关,”true”or“false”,还可以使用spring.hsf.delay-publishes.=
为具体某个服务设置是否延迟。String无spring.hsf.core-pool-size否服务的全局最小活跃线程数,还可以使用spring.hsf.core-pool-sizes.=
单独为某服务设置最小活跃线程数。int无spring.hsf.max-pool-size否服务的全局最大活跃线程数,还可以使用spring.hsf.max-pool-sizes.=
单独为某服务设置最大活跃线程数。int无spring.hsf.serialize-type否服务的全局序列化类型,Hessian或者Java,还可以使用spring.hsf.serialize-types.=
单独为某服务设置序列化类型。String无
4.3.2 本地开发测试
配置轻量级配置及注册中心。本地开发调试时,需要使用轻量级配置及注册中心,轻量级配置及注册中心包含了服务注册发现服务端的轻量版。
启动应用。
- 在IDE中启动:通过VM options配置启动参数-Djmenv.tbsite.net={$IP},通过main方法直接启动。其中
{$IP}
为轻量配置中心的IP地址。例如本机启动轻量配置中心,则{$IP}
为127.0.0.1
。 - 您也可以不配置JVM的参数,而是直接通过修改hosts文件将
jmenv.tbsite.net
绑定为轻量配置中心的IP。
通过FatJar启动
增加taobao-hsf.sar依赖,这样会下载到我们需要的依赖:/.m2/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar,在后面的启动参数中依赖它。
com.taobao.pandora
taobao-hsf.sar
2019-06-stable
使用Maven将Pandora Boot工程打包成FatJar, 需要在pom.xml中添加如下插件。为避免与其他打包插件发生冲突,请勿在build的plugin中添加其他FatJar插件。
com.taobao.pandora
pandora-boot-maven-plugin
2.1.11.8
package
repackage
添加完插件后,在工程的主目录下,执行Maven命令mvn clean package
进行打包,即可在Target目录下找到打包好的FatJar文件。
通过Java命令启动应用。
java -Djmenv.tbsite.net=127.0.0.1 -Dpandora.location=${M2_HOME}/.m2/repository/com/taobao/pandora/taobao-hsf.sar/2019-06-stable/taobao-hsf.sar-2019-06-stable.jar -jar hsf-pandora-boot-provider-1.0.jar
说明 -Dpandora.location
指定的路径必须是全路径,使用命令行启动时,必须显示指定taobao-hsf.sar的位置。访问consumer所在机器的地址,可以触发consumer远程调用provider。
curl localhost:8080/hsf-echo/helloworld
helloworld
4.3.3 单元测试
Pandora Boot的单元测试可以通过PandoraBootRunner启动,并与SpringJUnit4ClassRunner无缝集成。在Maven中添加Pandora Boot和Spring Boot测试必要的依赖。
com.taobao.pandora
pandora-boot-test
test
org.springframework.boot
spring-boot-starter-test
test
@RunWith(PandoraBootRunner.class)
@DelegateTo(SpringJUnit4ClassRunner.class)
// 加载测试需要的类,一定要加入Spring Boot的启动类,其次需要加入本类。
@SpringBootTest(classes = {HSFProviderApplication.class, HelloServiceTest.class })
@Component
public class HelloServiceTest {
/**
* 当使用 @HSFConsumer时,一定要在 @SpringBootTest类加载中,加载本类,通过本类来注入对象,否则当做泛化时,会出现类转换异常。
*/
@HSFConsumer(generic = true)
HelloService helloService;
//普通的调用。
@Test
public void testInvoke() {
TestCase.assertEquals("hello world", helloService.echo("hello world"));
}
//泛化调用。
@Test
public void testGenericInvoke() {
GenericService service = (GenericService) helloService;
Object result = service.$invoke("echo", new String[] {"java.lang.String"}, new Object[] {"hello world"});
TestCase.assertEquals("hello world", result);
}
//返回值Mock。
@Test
public void testMock() {
HelloService mock = Mockito.mock(HelloService.class, AdditionalAnswers.delegatesTo(helloService));
Mockito.when(mock.echo("")).thenReturn("beta");
TestCase.assertEquals("beta", mock.echo(""));
}
}
博文参考
启动轻量级配置及注册中心 - 企业级分布式应用服务 EDAS - 阿里云
开发HSF应用(Pandora Boot) - 企业级分布式应用服务 EDAS - 阿里云