目前工作中碰到一个问题:有一个SVN服务器,有一个构建服务器用来构建SVN上的项目,还有许多的应用服务器,其中应用服务器的程序正是由SVN的项目产生的。开发人员在SVN上提交新代码,版本之后,希望在所有应用服务器上有所体现,而不需要人工干预。
(Bamboo是澳大利亚Atlassian 公司出的一个商业持续集成构建服务器,基于Java,相比Hudson,具备更多的企业特征。起步价只需要10$元喔)
由于这种需求太具体,没法套用现成的框架。但是通过一些技术的组合,可以以非常小的代价来实现。
(Word的Bug,红点旁边应该有Agent字样的)
具体的过程可以描述为:
- 构建服务器从SVN下载源代码,执行构建
- 构建成功后,监听插件将会把产出物信息(artifact)以tcp方式通知部署服务器
- 部署服务器收到最新的artifact信息之后,将会按照某种策略通知所有应用服务器上的Agent
- Agent接收来自部署服务器信息,包括程序,放置在某个设定目录
- Agent停止服务器(或某个具体应用),替换相关文件,再启动服务器(或某个具体应用)。
这里部署服务器将会有两种类型的客户,一种产生Artifact,而另外一个消耗Artifact。
为原型简单起见,这里引入任何AIO,下载库之类的东西,全部使用Java描述。部署服务器一个类,Agent一个类,插件一个类。
原型将按照如下步骤进行:
第一步
创建一个支持构建工具的项目,常用的Java构建工具有Ant,Maven,存放到SVN服务器中
第二步
在Bamboo里面配置一个Plan,用来构建刚才创建的项目,值得注意的是,这个Plan一定要配置好Artifact,也就是产出物的匹配。比如刚才创建的是一个Maven web项目,它会产生一个war文件,在Plan里面的示例配置如下图:
选择Create Definition
第三步
虽然Bamboo很强大,但Notification机制里面并没有TCP通知之类的东东,我们需要创立一个插件完成部署服务器,产生了什么文件,放在哪。
Bamboo插件,包括Atlassian所有相关产品如JIRA,Fisheye,Cruible等都是基于OSGi的Fleix实现。我们可以按照Bamboo官方文档 http://confluence.atlassian.com/display/BAMBOO/Tutorial+1+-+Getting+Started+with+a+Simple+Post+Build+Labeller 先创建一个Build Complete Module,然后只保留Run方法,将其修改为:
public void run(Buildable buildable, BuildResults buildResult) {
final Collection<ArtifactLink> artifacts = buildResult.getBuildResultsSummary().getProducedArtifactLinks();
for (ArtifactLink link : artifacts) {
tcp_notify("path "+ link.getFile().getAbsolutePath());
}
}
这儿的tcp_notify就是连接上部署服务器,发一个path命令。
通过"atlas-mvn package"打包,按照bamboo手册放到相关目录(V2/V3目录不一致),插件就开发完成了。
第四步
部署服务器可能稍显复杂点,我稍微简化说出实现点:
public class BuildDeployServer {
public satic void main(String[] args) {
//1启动Server Socket
// 2 来一个客户端请求,创建一个Thread进行处理
}
}
class ClientThread extends Thread
{
public void run(){
//1 接收客户端的注册,按照Artifact产生者/消费者分类
//2 如果客户是产生者,则通知所有消费者客户端(消费者在没有Artifact的时候一般睡眠)
//3 如果客户是消费者,当前如果有Artifact,则开始于Agent通信,发送相关Artifact信息
}
}
第五步
编写Agent也非常的简单,如下:
Public class AppServerAgent{
public void main(String args[]){
//1 建立与部署服务器的连接并发送注册信息
//2 接受Artifact的相关信息,比如文件名,文件内容,hash等
//3 stopAppServer 或stopAppModule
//4 sleep一会
//5 完成文件替换
//6 startAppServer或startAppModule
}
}
第六步
按照应用服务器,部署服务器,构建工具,Agent逐个启动,然后在构建控制台里构建某一个项目后,一系列自动部署的工作开始了。
当然严格意义上的自动构建部署还有需要东西需要完善,在我设计里面分别如下:
- 插件对产出物的项目,文件匹配策略,配置等
- 在应用服务器增多后,部署服务器要改造成为AIO,比如Linux Epoll,Windows AIO,Java NIO等等。
- 网络安全问题,防止被窥视或攻击。
- 穿越防火墙的问题
- 部署服务器往应用服务器Push改成Pull,即应用服务器上的Agent从服务器上获取artifact,减少部署服务器调度负担,这需要资源编码,多进/线程。
- Agent重启服务器的策略,比如时间策略半夜才重启等。
- 整个自动构建部署的相关日志,监控等。
欢迎来信讨论!