上篇写的页面上,留下一个超链接,查看每条任务的具体情况。现在完成这部分。 首先修改数据库结构,上篇已经建了websync.websync_peer表,现在继续: 继续阅读……
29 Sep 2011 Posted in dancer
上篇写的页面上,留下一个超链接,查看每条任务的具体情况。现在完成这部分。 首先修改数据库结构,上篇已经建了websync.websync_peer表,现在继续: 继续阅读……
26 Sep 2011 Posted in dancer
接上篇,加上分发过程查看的页面。这应该是一个很典型的翻页处理。
首先创建一个数据库表如下:
mysqlcreate table websync_peer (
id int not null auto_increment primary key,
begin_time timestamp not null default 0,
end_time timestamp on update current_timestamp,
url varchar(128) not null,
customer varchar(20) not null,
md5_hex char(32) default null
) engine=innodb;
然后把之前的peer_query()函数修改如下:
perlsub peer_query {
my $url = shift;
#这里的database和session都需要其他plugin的配合,见之前博客,不贴重复代码了
my $sth = database->prepare('insert into websync_peer (begin_time, url, customer) value (now(), ?, ?)');
$sth->execute($url, session->{login});
};
然后把gearman::client的功能改到mysql的UDFs内完成,做法见。
然后写翻页函数了~
perlget '/check' => sub {
my $from = params->{page} || 1;
my $user = session->{login};
my @urls;
my $count_sql = 'select count(id) count from websync_peer where customer = ?';
my $count_sth = database->prepare($sql);
$count_sth->execute( $user );
my $count = $count_sth->fetchrow_hashref->{count};
my $total_pages = int( $count / 20 + 1 );
return 'No url has been posted to purge.' unless $count;
return 'Selected page number out of range.' if $from > $total_pages;
my $url_sql = 'select id,url,begin_time from websync_peer where customer = ? order by id desc limit ?, 20';
my $url_sth = database->prepare($sql);
$url_sth->execute( $user, ($from - 1) * 20 );
while ( my $ref = $sth->fetchrow_hashref ) {
push @urls, $ref;
};
template 'check', { 'urls' => \@urls,
'prev' => $from > 1 ? $from - 1 : 1,
'next' => $from < $total_pages ? $from + 1 : $total_pages,
'last' => $total_pages,
};
};
对应的check.tt如下:
```html<html><head>
继续阅读……
20 Sep 2011 Posted in linux
大家讨论使用 Gearman 做分布式处理时,各机需要注册一个独立的 job 作为信息反馈,但是为了方便,Gearman::Worker
脚本 register_function
代码又要通用,于是想到了使用各自的 ip 地址作为 job 命名~
继续阅读……
16 Sep 2011 Posted in dancer
写程序这个事情,其实规划最麻烦。比方我其实并没留意过一个完整的同步分发系统都有哪些功能。权做练手,想到哪些写哪些好了。 最基础的部分:一个提交文件列表的页面,自动分析文件列表然后从源下载文件,中心下载完成后通知边缘节点开始; 其次:文件完整性的校验,同步和分发的进度报表页面,失败报表的重试选择和报警; 再次:系统分用户,不同用户可选节点指定分发,只查看当前用户的报表。 以上。 今天先完成最基础的部分。还是用dancer -a websync创建应用。然后创建views/websync.tt如下: ```html </head><body> 继续阅读……
08 Sep 2011 Posted in perl
群里听说lbnamed这么个东东,用perl实现的动态DNS服务器。程序包括三个perl模块:Stanford::DNSserver模块、Stanford::DNS模块、LBCD模块;三个perl程序:lbnamed主程序、poller探测程序、slbcd监控程序(这个有C语言的版本)。 继续阅读……
25 Aug 2011 Posted in nginx
昨晚和前21v的同事聊天,说到我离职后一些技术上的更新。其中有个给某大客户(游戏下载类)的特殊需求设计,因为文件大小差距很大——估计是大版本和补丁的区别——又走的是同一个域名,而squid在响应比较大的文件时,尤其是初次下载的时候,性能比较差,所以拆成两组服务器,squid服务于较小的文件,通过pull方式从peer层获取,nginx服务于较大的文件,通过push方式由peer层分发同步。外部发布域名一律解析到squid服务器组上,请求透传到peer层的nginx,nginx分析这个url的content-length,如果大于阈值,则不返回文件,而是302到nginx服务器组的独立域名下的相应url去。 继续阅读……
18 Aug 2011 Posted in perl
第三篇,看web部分。主程序cloudforecast_web里主要就是调用CloudForecast::Web的run()函数,接下来去看CloudForecast::Web。
照例还是加载配置,然后这里主要多了两个accessor:allowfrom和front_proxy。用来定制acl和代理的。从下文可以看到,分别是采用了Plack::Middleware::Access和Plack::Middleware::ReverseProxy两个模块进行控制。
然后是主要部分,通过Plack::Builder建立$app:
1、初始化:”my $app = $self->psgi;”,这里是调用父层”use Shirahata -base;”的psgi()函数完成的。稍后再看这个。
2、包装:取出前面说的allowfrom和front_proxy部分后,代码如下:
perl
$app = builder {
enable 'Plack::Middleware::Lint';
enable 'Plack::Middleware::StackTrace';
enable 'Plack::Middleware::Static',
path => qr{^/(favicon\.ico$|static/)},
root =>Path::Class::dir($self->root_dir, 'htdocs')->stringify;
$app;
};
真实加载顺序是倒序的,先加载Static.pm,用来服务静态文件,意即url路径为^/static/.*的,实际documentroot为./htdocs/;然后加载StackTrace.pm,用于开发调试的时候,向标准输出输出错误跟踪信息;最后是Lint.pm,用于检查请求/响应的格式是否正确。
然后是加载运行,使用Plack::Loader运行上面build出来的$app。方法如下:
perl
my $loader = Plack::Loader->load(
'Starlet',
port => $self->port || 5000,
host => $self->host || 0,
max_workers => 2,
);
$loader->run($app);
主要是两个参数,第一个是用来运行plack的服务器模块名称,常见的有starman/twiggy/corona/perlbal等等,这里写的这个Starlet,是基于HTTP::Server::PSGI模块添加预派生(prefork)/热部署(Server::Starter)/优雅重启等功能的一个服务器模块,原来叫的名字是”Plack::Server::Standalone::Prefork::Server::Starter”(简称PSSPSS)……
继续阅读……
18 Aug 2011 Posted in perl
接下来看radar部分,也就是探测主程序cloudforecast_radar,其中主要就是调用CloudForecast::Radar中的run()函数。 首先还是惯例,调用ConfigLoader模块加载配置文件; 然后是%SIG信号的定义,用来之后自动重运行的; 然后一个while true死循环: 1、循环里用select(undef,undef,undef,0.5)实现一个0.5秒的sleep; 2、第一个if语句,用来判断是否是父进程,并使用无阻塞的waitpid($pid,WNOHANG)等待子进程完成——即$kid==-1; 3、第二个if语句,用来强制退出死循环,条件是收到%SIG信号; 4、第三个if语句,确认当前时间超过计划中的执行时间(即离上次执行时间最近的整5分钟点),开始执行探测——采用fork()派生子进程。 5、子进程内容是从之前获取的配置文件内,轮询每一台设备,最终调用run_host()函数执行。 然后又是两个if语句,接在while里的last之后,等待子进程全部完成的。 继续阅读……
17 Aug 2011 Posted in perl
近三天学习cloudforecast,这是一个日本SA写的分布式监控的perl项目。日本的运维水平和perl水平,都让人羡慕啊…… 项目介绍: http://blog.riywo.com/2011/02/27/043646 demo网址: http://editnuki.info:5000/ 下载地址: https://github.com/kazeburo/cloudforecast 粗略的看了主要文件,主要是用Class::完成的OO,Plack::MiddleWare::完成的web,Gearman::Worker调用Data::*里的具体模块完成对服务器的监控抓取,然后调用RRDs完成监控数据图像的更新,在启动分布式的情况下,则用Gearman::Client传输监控数据给调用RRDs的worker。 继续阅读……
02 Aug 2011 Posted in monitor
接下来进入我不擅长的页面部分了。规划页面分为side和main,side中提供时间选择框/类型下拉选择框和提交按钮;main中展示最后形成的chart。 时间选择框是用js和css完成的,这个网上有很多,不过要同时支持多浏览器和分钟级别的选项的,目前就发现一个好用的。下载地址如下:http://chenlinux.com/images/uploads/Calendar.zip 然后创建cachemoni/public/cdn.html如下: ```html 继续阅读……
01 Aug 2011 Posted in monitor
上篇完成了xml的输出,这篇开始说charts图像的生成。我们采用fusioncharts的免费版,之前博客有提到另一个amcharts,不过amcharts的免费版会在图像左上角加上自己amcharts.com的广告标识……
从fusioncharts官网下载free版的压缩包,有20MB大,不过其中对我们这个小项目有用的只有MSLine.swf/MSBar2D.swf/fusioncharts.js等。
说明:
1、官网介绍上写了支持perl,不过下载包里只有php/asp/jsp/rails的class,没有perl的。所以还是得采用js的方式;
2、js下有setDataURL和setDataXML两个方法,不过官方强烈建议使用setDataURL方法,这种方法可接受的数据量比setDataXML大很多。
页面html很简单,加如下js代码即可:
javascript</script>
<script type="text/javascript">
var myChart = new FusionCharts("/Charts/MSBar2D.swf", "myChartId", "600", "500");
myChart.setDataURL(escape("/xml?begin=***&end=***&type=area"));
myChart.render("chartdiv");
</script>
要点在这个escape(),如果URL里带参数的话,必须用escape()转码,不然的话第一个&之后的所有参数都会丢失掉!
在调试中注意到,为了忽略缓存,setDataURL()会在url最后跟上一个随机1-4位数字参数&curr=1234然后再发起请求。
现在就可以访问页面看看了~嗯,可以看到图像中的中文字有问题。这是因为fusioncharts不认utf8的中文,必须输出gbk或者gb2312的xml数据才行。所以需要修改一些dancer的charset配置,把config.yml里的charset: UTF-8改成charset: GBK。然后重新请求,中文就正确显示了。
如下图:
继续阅读……
28 Jul 2011 Posted in monitor
准备使用funsioncharts绘图,其采用xml数据,在绘制line图的时候,就要从mysql里读取数据,并输出成xml格式,相关配置如下: ```perl package cachemoni; use Dancer ‘:syntax’; use Dancer::Plugin::Database; use POSIX qw(strftime); 继续阅读……
27 Jul 2011 Posted in monitor
准备两个表,一个存储原始数据,另一个存储每5分钟归总一次的数据。之后根据时间段绘制省份运营商性能图的时候,就直接从汇总表里获取数据;原始表留给详细查询。 数据库准备脚本如下: ```mysqlUSE myops; CREATE TABLE IF NOT EXISTS cdn_ori_record ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, ip INT(10) NOT NULL DEFAULT ‘0000000000’, isp ENUM(‘0’,’1’,’2’,’3’,’4’), area INT(4) NOT NULL DEFAULT ‘0000’, cur_date TIMESTAMP DEFAULT NOW(), cdn_time INT(10) NOT NULL DEFAULT ‘0’, cdn ENUM(‘CHINACACHE’,’DNION’,’FASTWEB’) NOT NULL, KEY time_key (cur_date) ); 继续阅读……
26 Jul 2011 Posted in monitor
话接上篇,ip整理出来,然后就是接一个ip地址,快速定位查找到它属于哪个ip段,然后返回具体的省份和运营商。因为之前的ip已经转换成数字,而且是顺序排列的,所以可以采用折半算法(二分法)。perl脚本如下:
```perl#!/usr/bin/perl -w
#my $ip = inet_aton(“$ARGV[0]”);
my $ip = inet_aton(get_test_ip());
my $file = $ARGV[1] || ‘iplist.txt’;
my $length = cat $file | wc -l
;
继续阅读……
25 Jul 2011 Posted in monitor
为了跟第三方监控做对比和作为备用,准备自己通过页面js返回数据做个监控。首先第一步,整理一个足够自己用的ip库。 首先,考虑调用会比较频繁,打算把内容尽可能归并,到省级运营商即可; 其次,未知归并完会有多大的情况下,考虑到qqwry的地区都是中文,打算统一使用电话区号代替地区,运营商也有一位数字代替,ip采用inet-aton网络值代替;这样每条记录的字节数固定,可以方便采用seek和sysread提高读取某条记录的速度。 继续阅读……
21 Jul 2011 Posted in perl
原贴地址:http://bbs.chinaunix.net/thread-3563215-1-1.html flw回帖里有翻译,我试答如下: 继续阅读……
08 Jul 2011 Posted in monitor
上篇加了bash_history的监控,这篇说mysql_history的监控。不像bash4,mysql自始至终没有提供过syslog的代码,只能自己通过守护进程去实时获取~/.mysql_history的记录了。一个小脚本如下: ```perl#!/usr/bin/perl -w use POE qw(Wheel::FollowTail); use Log::Syslog::Fast qw(:all); 继续阅读……
08 Jul 2011 Posted in monitor
@钚钉钬影 童鞋要试验系统日志收集处理,采用rsyslog+loganalyzer做界面,因为需求有把bash_history也带上,所以采用修改bash源码的方式。最先采用了bash4.2(bash4.2已经带了这个功能,但是默认不开启,删掉哪个/**/就行了),不过因为这个bash4.+跟redhat的network-functions脚本有点小矛盾,重启的时候报个错——虽然改起来也很简单,就是加一个./的事情——不过本着尽量改动少的原则,换回bash3.1。 bash3.1里默认没有记录syslog的代码,所以从bash4.2/bashhist.c里复制有关bash_syslog_history代码段到bash3.1中——注意不是原样复制到bashhist.c,那样不顶用——需要复制到lib/readline/history.c中,如下: 继续阅读……
28 Jun 2011 Posted in dancer
squid监控之前有一篇关于snmp的内容,不过这次是真要用上了,所以细细挑出来几个做监控。碰巧凯哥更新了一把modern perl的东西,我亦步亦趋,也试试dancer。不过花了两天时间,DBIx::Class::Schema还是没搞出来,最终还是简单的用DBI跳过了…… 用的database就是之前nmap试验时生成的数据,有application/channel/intranet等column。 首先安装: ```perlcpanm Dancer DBI DBD:mysql Template Dancer::Session::YAML dancer -a cachemoni 继续阅读……
23 Jun 2011 Posted in linux
做运维几年没用过patch,说来也怪了~~趁着上一篇自己的小改动,熟悉一下这个命令的简单用法。
首先是patch的制作,用diff命令。
bashtar zxvf squid-2.7.STABLE9.tar.gz
cp squid-2.7.STABLE9 squid-2.7.STABLE9-old && mv squid-2.7.STABLE9 squid-2.7.STABLE9-new
#然后按照上篇的内容修改squid-2.7.STABLE9-new/里的文件
diff -uNr squid-2.7.STABLE9-old squid-2.7.STABLE9-new > squid-snmp.patch
这就完成了,好简单啊~来看看patch文件的内容吧:
```cdiff -uNr squid-2.7.STABLE9-old/include/cache_snmp.h squid-2.7.STABLE9-new/include/cache_snmp.h
— squid-2.7.STABLE9-old/include/cache_snmp.h 2006-09-22 10:49:24.000000000 +0800
+++ squid-2.7.STABLE9-new/include/cache_snmp.h 2011-06-23 13:25:04.000000000 +0800
@@ -125,6 +125,7 @@
MESH_PTBL_KEEPAL_S,
MESH_PTBL_KEEPAL_R,
MESH_PTBL_INDEX,
继续阅读……
22 Jun 2011 Posted in monitor
做反向代理的squid集群监控,在单机维护时,squidclient mgr:server_list里的OPEN CONNS是经常看的一项数据,不过在开启snmp支持后,在mib里却没有找到相关的数据。还一度怀疑是不是cachePeerKeepAlRecv或者cachePeerKeepSent。今天想起来去src里grep了一把源码,顺利的在squid/src/neighbors.c里看到了OPEN CONNS等数据的来源,如下:
cstatic void
dump_peers(StoreEntry * sentry, peer * peers)
{
peer *e = NULL;
……
for (e = peers; e; e = e->next) {
……
storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
……
storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
然后在squid/src/snmp_agent.c里看到了这些数据的snmp输出,如下:
cvariable_list *
snmp_meshPtblFn(variable_list * Var, snint * ErrP)
{
variable_list *Answer = NULL;
struct in_addr *laddr;
int loop, index = 0;
char *cp = NULL;
peer *p = NULL;
int cnt = 0;
……
switch (Var->name[LEN_SQ_MESH + 2]) {
case MESH_PTBL_NAME:
cp = p->name;
Answer = snmp_var_new(Var->name, Var->name_length);
……
case MESH_PTBL_KEEPAL_R:
Answer = snmp_var_new_integer(Var->name, Var->name_length,
p->stats.n_keepalives_recv,
SMI_COUNTER32);
break;
case MESH_PTBL_INDEX:
Answer = snmp_var_new_integer(Var->name, Var->name_length,
index,
ASN_INTEGER);
break;
default:
*ErrP = SNMP_ERR_NOSUCHNAME;
break;
}
return Answer;
}
一对比,发现确实没有stats.conn_open输出……
好在这个比较简单,稍微改一下,就能搞出来:
1、修改squid/include/cache_snmp.h如下:
cenum { /* cachePeerTable */
……
MESH_PTBL_CONN_OPEN, /*新增这个*/
MESH_PTBL_HOST,
MESH_PTBL_END
};
2、修改squid/src/snmp_core.c如下:
继续阅读……
14 Jun 2011 Posted in testing
小型的mysql测试工具,主要有自带的mysqlslap、super-smack和mybench。嗯,我这里的小型的意思是指工具安装过程简单。
mysqlslap的使用方法遍地都是,就不先详细写了。根据个人偏好写写mybench吧,毕竟是perl的。
安装很简单,如下:
bashcpanm DBI DBD::mysql Time::HiRes
wget http://jeremy.zawodny.com/mysql/mybench/mybench-1.0.tar.gz
tar zxvf mybench-1.0.tar.gz
cd mybench-1.0
perl MakeFile.PL && make && make install
但是使用就不是太简单了——mysqlslap会自己生成(-a选项)sql,super-smack则带了一个gen-data程序生成数据然后自动导入,但是mybench没有,所以只能自己搞定数据。
不过mybench还是自己生成了一个测试模版的脚本在/usr/bin/bench_example,很简单的就知道怎么做了。
example如下:
```perl#!/usr/bin/perl -w
继续阅读……
09 Jun 2011 Posted in perl
今天写基调测试报告,需要从原始的ping延时和丢包率数据中自己计算标准方差以评估波动性(直接运行ping命令可见,不过基调报告里没有)。
方差是各个数据与其平均数的差的平方的平均数。标准差(均方差)则是方差的算术平方根。
这个时候可以打开excel……不过作为excel只会填文字的人,只好打开CPAN来解决问题了~
perl#!/usr/bin/perl -w
use Statistics::Descriptive;
use strict;
open FH,'<','data';
my $data={};
while(<FH>){
my @F = split;
push @{$data->{"快网延时"}}, $F[3];
push @{$data->{"快网丢包"}}, $F[4];
push @{$data->{"森华延时"}}, $F[6];
push @{$data->{"森华丢包"}}, $F[7];
push @{$data->{"帝联延时"}}, $F[9];
push @{$data->{"帝联丢包"}}, $F[10];
}
close FH;
my $stat = Statistics::Descriptive::Full->new();
foreach my $key (sort keys %{$data}) {
$stat->add_data(@{$data->{"$key"}});
print $key."\t".$stat->standard_deviation(),"\n";
$stat->clear();
}
记住一定要clear,不然的话add_data会接着上一次的加,然后数据就错了。
继续阅读……
09 Jun 2011 Posted in perl
spread还是半年前的时候偶然看到的,一直没有试过。前段时间用gearman收集集群日志时,发现gearman的方式,worker不会知道client来自哪里,一条job只会一个worker来做,比较适合做分布式计算,但相比我最初设想的实时系统管理需求,还是有一定距离。于是重新翻出来spread,感觉可以根据应用系统设置不同的group,然后统一再由一个回收结果的group即可。于是有了如下试验: 继续阅读……