John: 现在测试环境8月16号的发布分支用的是哪个MQ?(看来这家伙被指派了一个缺陷修复 )Jane: 我看看……(一小会之后),是tcp://192.168.1.13:61617过了一会……
Andy:现在测试环境8月28号的发布分支用的是哪个MQ?Jane: 我看看……(一小会之后),是tcp://192.168.1.14:61617事实上,有时不同的开发人员会向配置管理员询问同一个发布分支的broker地址。由于它们不容易与对应的环境联系起来而且多少还是需要占用一些硬件资源的,于是我们决定裁剪ActiveMQ实例。
首先改造的是集成测试。我们原来为流水线的commit阶段准备了一台Server mode的ActiveMQ,但其实在集成测试中,我们更关心的是集成的代码和相关的配置。这时可以使用embedded mode的ActiveMQ替代,这样它们就变为了环境不敏感了,而且由于不需要持久化,每次集成测试都可以运行在一个“干净”的环境中。
runtime.properties:
runtime.messaging.broker.url=vm://localhost:61616?broker.persistent=false
不过embedded mode不能解决所有问题,当流水线晋级到自动部署后的自动化验收测试或手工验收测试时,还是server mode的ActiveMQ在排查问题时更方便。我们发现,应用程序并不是对整个消息中间件依赖,而是对消息中间件中的某个队列依赖,而不同的队列之间是不需要相互通信的,所以其实我们只需要一台server mode的ActiveMQ,让不同的环境依赖于不同的队列就可以了。这就要求不同环境使用不同的队列名字,但是队列的名字一般是通过代码中硬编码 /properties文件配置或是通过JNDI查找的,我们也不想因此增加配置负担。因此使用了使用环境名+固定队列名的队列名字拼接办法,比如:
notificationReceivedQueue --> commit.notificationReceivedQueue --> uat.notificationReceivedQueue --> pre.notificationReceivedQueue --> pro.notificationReceivedQueue
于是我们引入了一个Configurations类,它有点类似于一个Facade,提供易用的接口:
public class Configurations {
private String jmsEnvironment = "commit";
public String getNotificationReceivedQueueName() {
return jmsEnvrironmentSpecified("notificationReceivedQueue");
}
private String jmsEnvrironmentSpecified(String destinationName) {
return jmsEnvironment + "." + destinationName;
}
}
而配置中,可以使用spring el来注入队列名称
xml
queue-name="#{configurations.getNotificationReceivedQueueName() }"
这样,开发人员可以只访问一个broker,而通过队列名称来查找他的目标,uat0816.notificationReceivedQueue的可读性可要好多了。
实践持续交付是一个长期的渐进式的过程,往往会遇到各种个性化的问题。有的组织硬件资源不足,有的组织硬件资源充足,但还不能做到自动化环境管理。于是许多准备尝试部署流水线的团队会在流水线环境准备上遇到困难,希望这个故事能对这样的团队有帮助。有时候,外部环境或自身资源的限制也不完全是件坏事,这使我们停下细细思考,到底流水线的方案还有哪些可以改进的余地,办法总比困难多。
[1] 《持续交付——发布可靠软件的系统方法》by Jez Humble & David Farley
[2] 虽然hsqldb提供了与oracle不错的兼容性,但团队需要留意一些细节上的差别。
[3] 即不修改数据库,只增加新的数据库对象或是在现有对象上新增字段等,一般情况下应用程序比较容易做到对此的兼容性
[4] 据我所知创建一个新的用户所消耗的硬件资源很少,主要是其本身数据的存储空间,如果团队对测试数据进行管理的话,这个测试数据集应该不会太大。
[5] 轻易的使用数据库集成很容易抵消你所做的解耦努力。各个模块和子系统表面上看来还不错,但当数据结构改动时牵一发而动全身。
原文转自:http://www.kuqin.com/shuoit/20131215/336973.html