写个同步分发系统(二)

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> 继续阅读……


linux上获取本机ip的各种perl写法

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> 继续阅读……


lbnamed代码浅读

08 Sep 2011 Posted in  perl

群里听说lbnamed这么个东东,用perl实现的动态DNS服务器。程序包括三个perl模块:Stanford::DNSserver模块、Stanford::DNS模块、LBCD模块;三个perl程序:lbnamed主程序、poller探测程序、slbcd监控程序(这个有C语言的版本)。 继续阅读……


用nginx区分文件大小做出不同响应

25 Aug 2011 Posted in  nginx

昨晚和前21v的同事聊天,说到我离职后一些技术上的更新。其中有个给某大客户(游戏下载类)的特殊需求设计,因为文件大小差距很大——估计是大版本和补丁的区别——又走的是同一个域名,而squid在响应比较大的文件时,尤其是初次下载的时候,性能比较差,所以拆成两组服务器,squid服务于较小的文件,通过pull方式从peer层获取,nginx服务于较大的文件,通过push方式由peer层分发同步。外部发布域名一律解析到squid服务器组上,请求透传到peer层的nginx,nginx分析这个url的content-length,如果大于阈值,则不返回文件,而是302到nginx服务器组的独立域名下的相应url去。 继续阅读……


CloudForecast学习笔记(三)

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)…… 继续阅读……


CloudForecast学习笔记(二)

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之后,等待子进程全部完成的。 继续阅读……


CloudForecast学习笔记(一)

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。 继续阅读……


cdn自主监控(六):数据展示页面

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 继续阅读……


cdn自主监控(五):生成charts图像

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。然后重新请求,中文就正确显示了。 如下图: 继续阅读……


cdn自主监控(四):输出xml数据

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); 继续阅读……


cdn自主监控(三):数据库准备工作

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) ); 继续阅读……


cdn自主监控(二):快速查找ip对应信息

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; 继续阅读……


cdn自主监控(一):整理一个可用范围内的尽可能小的ip库

25 Jul 2011 Posted in  monitor

为了跟第三方监控做对比和作为备用,准备自己通过页面js返回数据做个监控。首先第一步,整理一个足够自己用的ip库。 首先,考虑调用会比较频繁,打算把内容尽可能归并,到省级运营商即可; 其次,未知归并完会有多大的情况下,考虑到qqwry的地区都是中文,打算统一使用电话区号代替地区,运营商也有一位数字代替,ip采用inet-aton网络值代替;这样每条记录的字节数固定,可以方便采用seek和sysread提高读取某条记录的速度。 继续阅读……


perl小测试题(转自CU)

21 Jul 2011 Posted in  perl

原贴地址:http://bbs.chinaunix.net/thread-3563215-1-1.html flw回帖里有翻译,我试答如下: 继续阅读……


mysql_history_monitor

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); 继续阅读……


bash_syslog_history

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中,如下: 继续阅读……


squid监控+dancer小试验

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 继续阅读……


patch制作和使用

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, 继续阅读……


给squid的snmp增加open_conn输出

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如下: 继续阅读……


mysql测试小工具mybench试用

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 继续阅读……


java的中文支持

10 Jun 2011 Posted in  linux

往论坛上传图片,有的图片上有中文字,却显示成方框。求助了一下度娘,快速解决。记录一下: 继续阅读……


perl模块Statistics::Descriptive

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会接着上一次的加,然后数据就错了。 继续阅读……


spread试验

09 Jun 2011 Posted in  perl

spread还是半年前的时候偶然看到的,一直没有试过。前段时间用gearman收集集群日志时,发现gearman的方式,worker不会知道client来自哪里,一条job只会一个worker来做,比较适合做分布式计算,但相比我最初设想的实时系统管理需求,还是有一定距离。于是重新翻出来spread,感觉可以根据应用系统设置不同的group,然后统一再由一个回收结果的group即可。于是有了如下试验: 继续阅读……


tmpfs的inode问题

09 Jun 2011 Posted in  linux

一些squid服务器为了强调加速效果,使用tmpfs来做cache_dir。刚开始运行的时候也嗖嗖的,不过没过一两天,mgr:info就看到缓存命中率急剧下降,字节命中率甚至只剩下10%左右!检查了多次配置,绝对没有问题,但同样的url,曾经一分钟几百次的HIT,现在一分钟几百次MISS…… df看,不管是tmpfs,还是logs所在的目录,都才用了不到30%。最后想起来df -i看了下,果然,tmpfs的inode使用率100%了! 赶紧remount了一次,解决了问题。但不是根本出路。还是得想办法搞定这个inode。 在linux代码说明里找到了关于tmpfs的文档(/usr/src/linux/Documentation/filesystems/tmpfs.txt): tmpfs has three mount options for sizing: …… nr_inodes: The maximum number of inodes for this instance. The default is half of the number of your physical RAM pages, or (on a machine with highmem) the number of lowmem RAM pages, whichever is the lower. These parameters accept a suffix k, m or g for kilo, mega and giga and can be changed on remount. The size parameter also accepts a suffix % to limit this tmpfs instance to that percentage of your physical RAM: the default, when neither size nor nr_blocks is specified, is size=50% 继续阅读……