Spring——Alibaba-pandora boot实战
阿里的Pandora Boot的核心是Pandora,因此在介绍Pandora Boot之前需要先介绍Pandora。在阿里集体内部,几乎所有的应用都用到了各式各样的中间件,比如HSF、TDDL、Diamond等等。本身中间件之间可能就有版本依赖的问题,比如你的应用HSF和Diamond分别依赖了同名jar包的不同版本,maven只会引入其中一个版本。同样的中间件和应用之间也存在同样的Jar包依赖
摘要
阿里的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了。
- 中间件升级困难:如果要实时升级中间件到推荐版本,但是发现并没有那么容易,应用中引入了十个八个中间件,隔三差五其中一个中间件就有小版本更新,每天盯着中间件的更新情况,那还有时间关心业务的开发了。
二、Alibaba-pandora boot的功能
- 实现类隔离,提供稳定的运行环境: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 等系统进行打通,开发起来更加的方便。
三、Alibaba-pandora boot的原理
四、Alibaba-pandora boot的实战演示
4.1 环境配置
4.1.1 安装轻量服务注册与发现中心
开发者可以在本地使用轻量级配置及注册中心实现应用的注册、发现和配置管理,完成应用的开发和测试。在将应用部署到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
定位启动失败的原因,并修复。
4.1.2 Maven中配置 EDAS 的私服地址
目前Spring Cloud for Aliware的第三方包只发布在EDAS的私服中,所以需要在Maven中配置EDAS的私服地址。本地开发调试时,需要启动轻量级配置注册中心。轻量级配置及注册中心包含了服务发现和配置管理功能。
在Maven中配置EDAS的私服地址
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
| This is the configuration file for Maven. It can be specified at two levels:
|
| 1. User Level. This settings.xml file provides configuration for a single user,
| and is normally provided in ${user.home}/.m2/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -s /path/to/user/settings.xml
|
| 2. Global Level. This settings.xml file provides configuration for all Maven
| users on a machine (assuming they're all using the same Maven
| installation). It's normally provided in
| ${maven.conf}/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -gs /path/to/global/settings.xml
|
| The sections in this sample file are intended to give you a running start at
| getting the most out of your Maven installation. Where appropriate, the default
| values (values used when the setting is not specified) are provided.
|
|-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>/root/.m2/repository</localRepository>
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->
<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false
<offline>false</offline>
-->
<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>
<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>
<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
-->
<!-- Another sample, using keys to authenticate.
<server>
<id>siteServer</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
-->
</servers>
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
<mirrors>
<!-- 阿里云仓库 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
</mirrors>
<!-- profiles
| This is a list of profiles which can be activated in a variety of ways, and which can modify
| the build process. Profiles provided in the settings.xml are intended to provide local machine-
| specific paths and repository locations which allow the build to work in the local environment.
|
| For example, if you have an integration testing plugin - like cactus - that needs to know where
| your Tomcat instance is installed, you can provide a variable here such that the variable is
| dereferenced during the build process to configure the cactus plugin.
|
| As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
| section of this document (settings.xml) - will be discussed later. Another way essentially
| relies on the detection of a system property, either matching a particular value for the property,
| or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
| value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
| Finally, the list of active profiles can be specified directly from the command line.
|
| NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
| repositories, plugin repositories, and free-form properties to be used as configuration
| variables for plugins in the POM.
|
|-->
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>edas.oss.repo</id>
<repositories>
<repository>
<id>edas-oss-central</id>
<name>taobao mirror central</name>
<url>http://edas-public.oss-cn-hangzhou.aliyuncs.com/repository</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>edas-oss-plugin-central</id>
<url>http://edas-public.oss-cn-hangzhou.aliyuncs.com/repository</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
<activeProfile>edas.oss.repo</activeProfile>
</activeProfiles>
</settings>
测试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环境
4.2源码样例
4.2.1 源码下载地址
SpringPrinciple: SpringPrinciple
4.3 运行与测试
4.3.1 项目结构说明
hsf-pandora-boot-provider的Maven工程
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<pandora-boot.version>2019-06-stable</pandora-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>pandora-hsf-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-starter-bom</artifactId>
<version>${pandora-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-maven-plugin</artifactId>
<version>2.1.11.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
虽然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 | 是 | 服务对外提供的接口 | Class | java.lang.Object |
serviceVersion | 否 | 服务的版本号 | String | 1.0.0.DAILY |
serviceGroup | 否 | 服务的组名 | String | HSF |
clientTimeout | 否 | 该配置对接口中的所有方法生效,但是如果客户端通过methodSpecials属性对某方法配置了超时时间,则该方法的超时时间以客户端配置为准。其他方法不受影响,还是以服务端配置为准(单位ms) | int | -1 |
corePoolSize | 否 | 单独针对这个服务设置最小活跃线程数,从公用线程池中划分出来 | int | 0 |
maxPoolSize | 否 | 单独针对这个服务设置最大活跃线程数,从公用线程池中划分出来 | int | 0 |
delayedPublish | 否 | 是否延迟发布 | boolean | false |
includeFilters | 否 | 用户可选的自定义过滤器 | String[] | 空 |
enableTXC | 否 | 是否开启分布式事务GTS | boolean | false |
serializeType | 否 | 服务接口序列化类型,hessian或者java | String | hessian |
supportAsynCall | 否 | 是否支持异步调用 | String | false |
名称 | 示例 | 限制大小 | 是否可调整 |
---|---|---|---|
{服务名}:{版本号} | 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工程
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<pandora-boot.version>2019-06-stable</pandora-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>pandora-hsf-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-starter-bom</artifactId>
<version>${pandora-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-maven-plugin</artifactId>
<version>2.1.11.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
将服务提供者所发布的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 | 否 | 服务的组名 | String | HSF |
serviceVersion | 否 | 服务的版本号 | String | 1.0.0.DAILY |
clientTimeout | 否 | 客户端统一设置接口中所有方法的超时时间(单位ms) | int | -1 |
generic | 否 | 是否支持泛化调用 | boolean | false |
addressWaitTime | 否 | 同步等待服务注册中心( ConfigServer )推送服务提供者地址的时间(单位ms) | int | 3000 |
proxyStyle | 否 | 代理方式(JDK或Javassist) | String | jdk |
futureMethods | 否 | 设置调用此服务时需要采用异步调用的方法名列表以及异步调用的方式,默认为空,即所有方法都采用同步调用 | String[] | 空 |
consistent | 否 | 负载均衡是否使用一致性哈希 | String | 空 |
methodSpecials | 否 | 配置方法级的超时时间、重试次数、方法名称 | com.alibaba.boot.hsf.annotation.HSFConsumer.ConsumerMethodSpecial[] | 空 |
属性 | 是否必配 | 描述 | 类型 | 默认值 |
---|---|---|---|---|
spring.hsf.version | 否 | 服务的全局版本号,还可以使用spring.hsf.versions.<完整的服务接口名>=<单独为该服务接口设置的版本号,String类型> ,例如spring.hsf.versions.com.aliware.edas.EchoService="1.0.0" 为具体某个服务设置版本号。 | String | 1.0.0.DAILY |
spring.hsf.group | 否 | 服务的全局组名,还可以使用spring.hsf.groups.<完整的服务接口名>=<单独为该服务接口设置的组名,String类型> 为具体某个服务设置组名。 | String | HSF |
spring.hsf.timeout | 否 | 服务的全局超时时间,还可以使用spring.hsf.timeouts.<完整的服务接口名>=<超时时间,String类型> 为具体某个服务设置超时时间。 | Integer | 无 |
spring.hsf.max-wait-address-time | 否 | 同步等待服务注册中心( ConfigServer )推送服务提供者地址的全局时间(单位ms ),还可以使用spring.hsf.max-wait-address-times.<完整的服务接口名>=<等待时间,String类型> 为具体某个服务设置的等待服务注册中心(ConfigServer)推送服务提供者地址的时间。 | Integer | 3000 |
spring.hsf.delay-publish | 否 | 服务延迟发布的全局开关,”true”or“false”,还可以使用spring.hsf.delay-publishes.<完整的服务接口名>=<是否延迟发布,String类型> 为具体某个服务设置是否延迟。 | String | 无 |
spring.hsf.core-pool-size | 否 | 服务的全局最小活跃线程数,还可以使用spring.hsf.core-pool-sizes.<完整的服务接口名>=<最小活跃线程数,String类型> 单独为某服务设置最小活跃线程数。 | int | 无 |
spring.hsf.max-pool-size | 否 | 服务的全局最大活跃线程数,还可以使用spring.hsf.max-pool-sizes.<完整的服务接口名>=<最大活跃线程数,String类型> 单独为某服务设置最大活跃线程数。 | 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,在后面的启动参数中依赖它。
<dependency>
<groupId>com.taobao.pandora</groupId>
<artifactId>taobao-hsf.sar</artifactId>
<version>2019-06-stable</version>
</dependency>
使用Maven将Pandora Boot工程打包成FatJar, 需要在pom.xml中添加如下插件。为避免与其他打包插件发生冲突,请勿在build的plugin中添加其他FatJar插件。
<plugin>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-maven-plugin</artifactId>
<version>2.1.11.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
添加完插件后,在工程的主目录下,执行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测试必要的依赖。
<dependency>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
@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(""));
}
}
博文参考
更多推荐
所有评论(0)