[研发生态]持续集成之ant makefile 模版

关注 jenkins: 持续的软件版本发布/测试项目\监控外部调用执行的工作,当然这样的工具太弱了,才用(puppet,chef)自动化分布式运维+自定义脚本或程序才是非常强大的。

ant build.xml 版本发布build.xml 模板

<?xml version="1.0"?>
<project default="KscMonitor">
	<property name="src.dir" location="src"></property>
	<property name="current.dir" location="./WebRoot/WEB-INF/"></property>
	<property name="lib.dir" location="./WebRoot/WEB-INF/lib/"></property>
	<property name="build.dir" location="build"></property>
	<property name="build.jar" location="${build.dir}/jar"></property>
	<property name="build.war" location="${build.dir}/war"></property>
	<property name="build.war.classes" location="${build.war}/WEB-INF/classes"></property>
	<property name="build.war.lib" location="${build.war}/WEB-INF/lib"></property>
	<property name="build.classes" location="${build.dir}/classes"></property>
	<property name="build.test.classes" location="${build.dir}/test/classes"></property>
	
	<path id="compile-path">
		<fileset dir="${lib.dir}" includes="**/*.jar"></fileset>
	</path>
	
	<path id="test-compile-path">
		<path refid="compile-path"></path>
		<pathelement location="${build.classes}"/>
	</path>
	
	<path id="test-run-path">
		<path refid="test-compile-path"></path>
		<pathelement location="${build.dir}/test/classes"/>
	</path>
	
	<target name="clean">
		<delete dir="${build.dir}"></delete>
		<!--
		<delete dir="${lib.dir}"></delete>
		-->
	</target>
	
	<target name="init" depends="clean">
		<mkdir dir="${build.dir}"/>
		<mkdir dir="${build.jar}"/>
		<mkdir dir="${build.war}"/>
		<mkdir dir="${build.war.classes}"/>
		<mkdir dir="${build.war.lib}"/>
		<mkdir dir="${build.classes}"/>
		<mkdir dir="${build.dir}/test/classes"/>
		<copy todir="${build.war}/WEB-INF">
			<fileset dir="${current.dir}" includes="web.xml"></fileset>
			<fileset dir="${current.dir}" includes="kscmonitor.conf"></fileset>
		</copy>
	</target>
	
	<target name="compile" depends="init">
		<javac srcdir="${src.dir}" destdir="${build.classes}" classpathref="compile-path">
			<compilerarg value="-Xlint:unchecked"/>
		</javac>
	
		<copy todir="${build.classes}">
			<fileset dir="${src.dir}" excludes="**/*.java"></fileset>
		</copy>
			
	</target>
	
	<target name="war" depends="compile">
		<copy todir="${build.war.classes}">
			<fileset dir="${build.classes}"></fileset>
		</copy>
		<copy todir="${build.war.lib}">
			<fileset dir="${lib.dir}"></fileset>
		</copy>
		<copy todir="${build.war}">
			<fileset dir="./WebRoot" includes="**/*" excludes="WEB-INF/*"></fileset>
		</copy>
		<war destfile="${build.dir}/KSCMonitor.war" webxml="${build.war}/WEB-INF/web.xml">
			<fileset dir="${build.war}" />
			<lib dir="${build.war.lib}" />
			<classes dir="${build.war.classes}" />
		</war>
	</target>
</project>


makefile 模板- 子模块:

####################64Bit Mode####################
ifeq ($(shell uname -m),x86_64)
CC=gcc
CXX=g++
ifeq ($(coverage), yes)
CXXFLAGS=-g \
  -pipe \
  -W \
  -Wall \
  -coverage \
  -fPIC
COV=-lgcov
else
CXXFLAGS=-g \
  -pipe \
  -W \
  -Wall \
  -fPIC
COV=
endif
CPPFLAGS=-D_GNU_SOURCE \
  -D_USE_PBRPC \
  -D_DEBUG \
  -D__STDC_LIMIT_MACROS \
  -D__VERSION_ID__=\"1.0.0.0\" \
  -D__BUILD_HOST__=\"`whoami`@`hostname`\" \
  -D__GIT_INFO__=\"not_in_svn_repo\"
INCPATH=-I../
DEP_INCPATH=-I../common/output/include \
  -I../protocol/output/include \
  -I../lib/pandora/output/include \
  -I../third-party/zookeeper-3.4.6/output/include \
  -I../third-party/sofa-pbrpc/output/include \
  -I../third-party/protobuf-2.4.1/output/include \
  -I../third-party/snappy-1.1.1/output/include \
  -I../third-party/zlib-1.1.1/output/include
SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %.cpp, %.o, ${SRCS})
LIBOBJS := $(filter-out main.o , $(OBJS))

.PHONY:all
all:libdataserver.a dataserver
	@echo "[PHENIX:BUILD][Target:'all']"
	@echo "make all done"

.PHONY:ccpclean
ccpclean:
	@echo "[PHENIX:BUILD][Target:'ccpclean']"
	@echo "make ccpclean done"

.PHONY:clean
clean:ccpclean
	@echo "[PHENIX:BUILD][Target:'clean']"
	rm -rf libdataserver.a
	rm -rf ./output/lib/libdataserver.a
	rm -rf dataserver
	rm -rf ./output/bin/dataserver
	rm -rf $(OBJS)
	rm -rf output
	rm -rf *.gcno

.PHONY:dist
dist:
	@echo "[PHENIX:BUILD][Target:'dist']"
	tar czvf output.tar.gz output
	@echo "make dist done"

.PHONY:distclean
distclean:clean
	@echo "[PHENIX:BUILD][Target:'distclean']"
	rm -f output.tar.gz
	@echo "make distclean done"

libdataserver.a:$(LIBOBJS)
	@echo "[PHENIX:BUILD][Target:'libdataserver.a']"
	ar crs libdataserver.a $(LIBOBJS)
	mkdir -p ./output/lib
	cp -f --link libdataserver.a ./output/lib

dataserver:$(OBJS)
	@echo "[PHENIX:BUILD][Target:'dataserver']"
	$(CXX) $(OBJS) -Xlinker "-(" \
  ../protocol/output/lib/libprotocol.a \
  ../common/output/lib/libcommon.a \
  ../lib/pandora/output/lib/libpandora.a \
  ../third-party/protobuf-2.4.1/output/lib/libprotobuf-lite.a \
  ../third-party/protobuf-2.4.1/output/lib/libprotobuf.a \
  ../third-party/protobuf-2.4.1/output/lib/libprotoc.a \
  ../third-party/snappy-1.1.1/output/lib/libsnappy.a \
  ../third-party/zlib-1.2.8/output/lib/libz.a \
  ../third-party/sofa-pbrpc/output/lib/libsofa-pbrpc.a \
  ../third-party/zookeeper-3.4.6/output/lib/libzookeeper_mt.a\
  -lcrypto \
  -lpthread \
  -lrt ${COV} \
  ../third-party/gperftools-2.1/output/lib/libprofiler.a \
  ../third-party/gperftools-2.1/output/lib/libtcmalloc_minimal.a\
  -Xlinker "-)" -o dataserver
	mkdir -p ./output/bin
	cp -f --link dataserver ./output/bin

%.o : %.cpp
	@echo "[PHENIX:BUILD][Target:'dataserver/$@']"
	$(CXX) -c $(INCPATH) $(DEP_INCPATH) $(CPPFLAGS) $(CXXFLAGS)  -o $@ $<

endif #ifeq ($(shell uname -m),x86_64)

makefile  模板-All:

export ROOT := $(shell pwd)
SUB_DIRS := ${ROOT}/protocol ${ROOT}/common ${ROOT}/nameserver ${ROOT}/dataserver
PROTOCOL_DIR := ${ROOT}/protocol
COMMON_DIR := ${ROOT}/common
DATASERVER_DIR := ${ROOT}/dataserver
NAMESERVER_DIR := ${ROOT}/nameserver
PB_DIR=${ROOT}/third-party/protobuf-2.4.1/output/

.PHONY:all
all:protocol common nameserver dataserver
	@echo "[PHENIX:BUILD][Target:'all']"
	@echo "make all done"

.PHONY:protocol
protocol:
	@echo "[PHENIX:BUILD][Target:'protocol']"
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --cpp_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/common.proto
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --java_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/common.proto
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --cpp_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/name_server.proto
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --java_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/name_server.proto
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --cpp_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/data_server.proto
	@${PB_DIR}/bin/protoc -I=${PROTOCOL_DIR} --java_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/data_server.proto
	@${PB_DIR}/bin/protoc --proto_path=${PB_DIR}/include -I=${PROTOCOL_DIR} --java_out=${PROTOCOL_DIR} ${PROTOCOL_DIR}/client.proto
	${MAKE} -C ${ROOT}/protocol

.PHONY:common
common:
	@echo "[PHENIX:BUILD][Target:'common']"
	${MAKE} -C ${COMMON_DIR}

.PHONY:nameserver
nameserver:protocol common
	@echo "[PHENIX:BUILD][Target:'nameserver']"
	${MAKE} -C ${NAMESERVER_DIR}

.PHONY:dataserver
dataserver:protocol common
	@echo "[PHENIX:BUILD][Target:'dataserver']"
	${MAKE} -C ${DATASERVER_DIR}

.PHONY:test
test:common_test nameserver_test dataserver_test
	@echo "[PHENIX:BUILD][Target:'test']"
	@echo "make test done"

common_test:protocol common
	@echo "[PHENIX:BUILD][Target:'common_test']"
	${MAKE} -C ${COMMON_DIR}/test

nameserver_test:protocol common nameserver
	@echo "[PHENIX:BUILD][Target:'nameserver_test']"
	${MAKE} -C ${NAMESERVER_DIR}/test

dataserver_test:protocol common dataserver
	@echo "[PHENIX:BUILD][Target:'dataserver_test']"
	${MAKE} -C ${DATASERVER_DRIR}/test


.PHONY:clean
clean:
	@echo "[PHENIX:BUILD][Target:'clean']"
	${MAKE} -C ${PROTOCOL_DIR} clean
	${MAKE} -C ${COMMON_DIR} clean
	${MAKE} -C ${NAMESERVER_DIR} clean
	${MAKE} -C ${DATASERVER_DIR} clean
	${MAKE} -C ${COMMON_DIR}/test clean
	${MAKE} -C ${NAMESERVER_DIR}/test clean
	${MAKE} -C ${DATASERVER_DIR}/test clean


程序员的20个瓶颈工程实践

翻译内容转自:http://blog.csdn.net/maray/article/details/8351823

* Database (数据库)

  1. 数据规模超出了最大内存限制 —–服务器采购规划、考虑mmap映射、或索引机制实现。
  2. 大查询和小查询 —- 
  3. 写写冲突 —- cas 原子化,版本号实现
  4. 大表join超占内存 —–

* Virtualization (虚拟化)
  1. 共享磁盘,抢磁道,磁头各种抖 —- 设计好线程模型,最好单线程单磁头,现代机械硬盘一般多磁头
  2. 网络IO波动 —  预估好QPS和测试防护,大文件吞吐分片处理等等

* programming(编程)
  1. 线程:死锁、相对于事件驱动来说过于重量级、调试、线程数与性能比非线性
  2. 事件驱动编程:回调的复杂性、函数调用中如何保存状态(how-to-store-state-in-function-calls)
  3. 缺少profile工具、缺少trace工具、缺少日志工具 —— gperftool 、gtest、cplusplus log
  4. 单点故障、横向不可扩展 ——— zookeeper 
  5. 有状态的应用 ——– 状态机map预加载,redis 会话管理
  6. 搓设计:一台机器上能跑,几个用户也能跑,几个月后,几年后,尼玛,发现扛不住了,整个架构需要重写。———-持续优化
  7. 算法复杂度 
  8. 依赖于诸如DNS查找等比较搞人的外部组件(Dependent services like DNS lookups and whatever else you may block on.)
  9. 栈空间 —- 加内存、控制栈空间,使用轻量的线程、纤程,比如golang 、erlang 


* Disk (磁盘)
  1. 本地磁盘访问 ——- 使用优化的本地api ,比如sendfile mmap 等
  2. 随机磁盘IO ——-  使用合适的文件系统 ,根据场景 选择好譬如xfs 或ext4 等文件系统,增加访问文件的并发能力。
  3. 磁盘碎片 —– 小文件凑大block 组织,比如object storerage file system
  4. 当写入的数据块大于SSD块大小时SSD性能下降 —- 最好数据分片,凑整。


* OS (操作系统)
  1. Fsync flushing,Linux缓冲区耗尽(linux buffer cache filling up) —- 控制好fsync 时机和pagecache flush的时间。
  2. TCP缓冲区过小 —- 调整 sysctl.conf  配置
  3. 文件描述符数限制 —– 预设值ulimit , network fd reused
  4. 电源管理(Power budget) —– UPS


* Caching (缓存)
  1. 不使用memcached  ——  那就是用redis了,或者本服务自己实现。
  2. HTTP中,header,etags,不压缩(headers, etags, not gzipping)
  3. 没有充分使用浏览器缓存功能 –比如一些个缩略图,Cookie 
  4. 字节码缓存(如PHP)—– 
  5. L1/L2缓存. 这是个很大的瓶颈. 把频繁使用的数据保持在L1/L2中. 设计到的方面很多:网络数据压缩后再发送,基于列压缩的DB中不解压直接计算等等。有TLB友好的算法。最重要的是牢固掌握以下基础知识:多核CPU、L1/L2,共享L3,NUMA内存,CPU、内存之间的数据传输带宽延迟,磁盘页缓存,脏页,TCP从CPU到DRAM到网卡的流程。


* CPU
  1. CPU负载  — 检查软硬中断情况
  2. 上下文切换。一个核上线程数过多,linux调度器对应用不友好,系统调用过多— cpu亲缘性设计,top 检测
  3. IO等待->所有CPU都等起 
  4. CPU缓存。(Caching data is a fine grained process (In Java think volatile for instance), in order to find the right balance between having multiple instances with different values for data and heavy synchronization to keep the cached data consistent.)—– 读写弱一致性问题
  5. 背板总线的吞吐能力 — HBA \SCSI\RAID 卡等


* Network (网络)
  1.  网卡的最大输出带宽,IRQ达到饱和状态,软件中断占用了100%的CPU ——- 网卡设备故障,网络吞吐过大,使用 atop检查
  2. DNS查找  
  3. 丢包 —- 服务器问题,交换机buffer 溢出
  4. 网络路由瞎指挥  — 环路、隔离不当
  5. 网络磁盘访问 
  6. 共享SAN(Storage Area Network)
  7  服务器失败 -> 服务器无响应


* Process (过程)
  1. 测试时间 — 基本是代码编写时间的1.5倍
  2. 开发时间 — 团队能力评估、培训等
  3. 团队规模 — 3-5 是最佳团队
  4. 预算 — 团队建设、差旅、图文、加班等
  5. 码债(不良代码带来的维护成本)


* Memory (内存)
  1. 内存耗尽 -> 杀进程,swap —-做好设计预估和模拟测试,尽早发现内存泄露和内存喷井
  2. 内存不足导致的磁盘抖动 —- 做好设计预估和模拟测试,尽早发现内存泄露
  3. 内存库的开销 — java 使用LinkedHashMap 实现LRU 对象池,c或c++ 尽量尽量是gperftool
  4. 内存碎片 —-Java 的时候你需要用到jstat 、jstack、MemoryAnalyzer插件、jmap ,C或c++ 尽量使用tcmalloc 避免arena


业务计数 日志 数据分析

    在设计实现后台服务时,为了方便以后对一些业务日志进行数据分析,我们需要对后台服务的日志打印定规范,同时需要对业务操作进行计数。

后台服务常使用atomic变量+report thread 实现。每个统计时间粒度做一次统计,打印日志后即flash清除重新统计。

    临时或简单的数据处理可以使用shell、awk等命令工具实现。

    长期、大数据需要建数据仓库,并定时拉取到hadoop或 RDB 中。

    可视化可采用web + highchart 技术实现前端显示。

分布式系统常用名词

replicas 复制,动词

replication 副本,名词

master 描述服务级别的主

slave 描述服务级别的备

shallow 影子

standby 站在旁边,准备行动,替换上来。

primary 比如在object storeage中描述主block

seconds 比如在object storeage中描述副block

part 比如EC编码后的part

companion  伙伴

compact  压紧,比如清理已标记删除的object文件

Heatbeat 心跳

fail over 失效转移,比如有slave备份服务

fail restart 失效拉起,比如某个服务crash挂了后,依然能拉起。

fail fast 快速失败

fault-tolerant  失效容忍

Auto-Degrade 自动降级

常用shell脚本笔记

数组处理:

declare -a sha
> com.log
while read line
do
    sha=($line)
    blockid=${sha[0]}
    for i in {1..3}
    do
    wget -O  ${sha[0]} ${sha[1]}"__"$i
    size=$(ls -l ${sha[0]}  | awk '{print $5}')
    if [ "$size" == "0" ]; then
        rm -f $blockid
        continue
    else
        echo ${sha[0]}" "${sha[1]}"__"$i >> com.log
        sha1=$(sha1sum $blockid | awk '{print $1}')
         wget -O - --timeout=100  "http://172.16.100.197:9001/upload/?filename=$blockid&sha1=${sha1}&size=${size}" --post-file=./$blockid
         if [ $? -eq 0 ]; then
         printf "end $line OK\n"
         rm -f ./$blockid
         else
         printf "end $line FAIL\n"
         rm -f ./$blockid
         fi
        break
    fi
    done

done < $1

远端SSH执行:

#!/usr/bin/expect  --


if { [llength $argv] != 2} {
	puts "usage: $argv0 ip \"command \[params\]\""
	exit 1
}


set maxRetry 1
for {set retryNum 0} {$retryNum<$maxRetry} {incr retryNum} {

spawn  /usr/bin/ssh [lindex $argv 0] [lindex $argv 1]

set timeout 80
expect {


 
	"yes/no)?" {
  
		send "yes\r"

		expect eof

		break

	}
  
	timeout {continue}
	eof {continue}

}
}

scp快速执行:

#!/usr/bin/expect --

puts "pcp.sh..."
if { [llength $argv] < 2} { 

    puts "usage: $argv0 ip filename"  
    exit 1
}
set success 0

set maxRetry 5
for {set retryNum 0} {$retryNum<$maxRetry} {incr retryNum} {

    spawn  /usr/bin/scp -r [lindex $argv 1] [lindex $argv 0]:/home/raojianlong

    set timeout 600
    expect { 

        "password:" {    	
            puts "input passwd"
            send "[lindex $argv 3]\r"	
            set timeout 600
            puts "try $retryNum"
            expect { 
                timeout {continue}
                eof {
                    set success 1
                    break
                }
            }
        }

        "yes/no)?" {
            puts "input yes"
            send "yes\r"
            expect "password:" {
                send "[lindex $argv 3]\r"
                set timeout 600
                expect { 
                    timeout {continue}
                    eof {
                        set success 1
                        break
                    }
                }
            }
        }

        timeout {continue}
        eof {
            set success 1
            break
        }
    }
}

puts "pcp sucess..."
if { $success==0 } {
    exit 1
}

安装脚本范式:

。。。

fun_main()
{
    start_id=${2%%-*}
    end_id=${2##*-}
    printf $1" from %s to %s ,confirm Y/N?:" $start_id $end_id
    read answer
    if [ "$answer" != "Y" ];then
        exit 1
    fi
    case "$1" in
        install)
        install $start_id $end_id
        ;;
        start)
        start $start_id $end_id
        ;;
        stop)
        stop $start_id $end_id
        ;;
        clear)
        clear $start_id $end_id
        ;;
    esac


}


关于心跳的设计讨论

在分布式系统设计里面,心跳是个很关键的东西,主要是用来了解服务进程的可用性:

    1、心跳是自己维护,还是交给像zookeeper这样的开源服务维护。

    2、租约协议实现。

    3、session 会话实现。

    

除了这些,心跳还可以负责一些汇报工作,比如磁盘容量、可用性等逻辑单元情况,还能收集nameServer的进一步意图;尽量保持心跳包的轻量。

聊云安全之IDC物理安全

    随着云计算的不断发展,云安全变得越来越重要,比较受重视的系统安全、网络安全和应用安全我这里就不聊,不是很懂,我就来聊聊IDC物理安全吧,因为之前在运营商机房呆过,而且

在老东家那一直管理着公司开发机房。以前我们的服务器都部署在自家机房,现在托管越来越流行了,做好第三方控制就变得越来越不简单,真的需要实地检验的,那么IDC有哪些东西呢?

    1、空调

    2、电源(插线板、电源线等)

    3、机架(rack)

    4、服务器

    5、交换机

    6、中控(温控、电控、核心交换机等)

    7、网线

    8、线扎、标签纸

    9、带外管理设备


1、空调温度最好控制在20度左右。

2、电源做到有UPS或服务器支持双线,双插线板(当然不同的插线板最好来自双工业供电,估计这个比较难),还是UPS靠谱。

3、控制好机架与机架之间以及服务器与服务器的之间机架间距,不要偷懒,服务器滚轮一定要用上,不要单纯的把服务器堆叠起来。

4、服务器和网线都得打标签,网线一定要罗顺了。保证网线不落地,不冗长,机架外不可触。网线一定要用最好的铜线。

5、交换机双线bond

6、中控一定要在不常见的位置,有必要一定要上锁。

7、线扎做好以后,一定剪掉多余的部分,防止人过触碰。

8、在想?

erasure code实现陷阱

ec应用object storage system 的时候,时常会进入某些细节的激烈争辩:

    1、关于block(volume)的垂直切割编码还是水平组合编码的问题,解释一下,假如我们的EC编码方式10+4,

        垂直切割编码:比如block 是个10G的定长块,需要把这个定长块切割成10个1G的,编码出4个校验块,然后把这个14个块分散分布在不同的机器上。

        水平组合编码:比如block 是个1G的定长块,那么我们需要从10台不同的机器上拉取10个1G的块,编码出4个校验块,然后把4个校验块分散分布在其他机器上。

    2、关于EC编码任务的责任方讨论,到底是交由nameServer维护任务过程,还是交由dataServer维护任务过程的问题。如果为了减少脏数据,就需要引入事务的问题。

        Ec编码、块的推送或拉取,都会出现异常,异常发生后怎么做容错恢复是个细节讨论的问题。

    3、怎么保证index数据一致性问题,EC locationMap 数据结构的设计

    4、EC编码组存放问题: DB 持久化存放 、 DataServer持久化存放、NameServer 持久化存放?

    5、在想呢!EC-Jerasure-1.2

关于单机DataServer或单盘单DataServer架构讨论

在设计存储相关系统时,我们时常陷入了关于DataNode或DataServer的单盘部署还是单机部署的争辩,那我们可以看看这两种设计部署方式有哪些优缺点:

    单机部署缺点:编程实现更加复杂;内存hold住足够的单机元数据;DataServer服务足够健壮,存在整机不可用的风险;踢盘需要外部第三方运维工具

    单机部署优点:NameServer的心跳、链接负担大大减轻;批量部署运维更加方便友好;


譬如TFS就采用单盘单DataServer的部署设计


    单盘部署缺点:部署运维不友好;NameServer的心跳、链接负担重;

    单盘部署优点;编程实现简单;踢盘自行可解决;服务不可用仅影响单盘,不影响整机盘;


譬如百度的存储系统就采用了单机单DataServer的部署设计


最终系统怎么去设计衡量取决于背景包袱、团队实力、老板给的时间及系统设计目标。