中午看了一下分享的wx消息架构设计文章,深有感触,但由于内容比较XX,不能分享,这里写一些简单总结
1、为了规避消息的ack,server只通知client 有消息了,client自己拉取消息。
2、client拉取消息带上当前最大自己最大id,防止消息丢失。这个设计的很好
3、client运行时通知策略和类apns通知策略的不同方式
4、优化的通知带内容体的方式,需要ack

      真是两篇好文,可是…,我只能默默的享受了。接下来遇到个问题,如果用户有10w,每个server只有2w的连接,那这10w是怎么安排哪些用户连接哪个server呢。中午问了richard,说根据dns,那分析如下

      dns不是一个好方法,通过dns获取域名的ip列表,轮询ip地址连接。这个有个问题,如果某一个ip机器挂掉了,需要剔除某ip需要修改dns,而dns生效很慢。且这种方式不能对server做权重控制。

      一开始自己意淫的方式,向某server发起连接获取一个相对性能较好的ip及端口,再向该ip发起连接请求,但这种方式需要两次连接,后来问了一个运维朋友,发了一篇文章: LVS负载均衡原理和算法详解 可以利用DR/TUN方式来实现,但具体在client上还不清楚有什么样的解决方案。

19 / 09 / 2013 admin

      话说很久没有写过文章了,自从离职后,进入tc也1个多月了,过的很忙,也很充实,现在发现比起后端我更爱前端,但潜意识还是觉得不够帅气,不够牛逼,所以还在努力挣扎着去接触cgi,原因也是因为这次的项目中有几个接口需要动态输出。现在回过头来看网站开发,把一个网站做牛逼,就应该把所有的静态化,动态内容全部异步或者定时生成再include,看业务需要。把所有的请求交给nginx来处理,至少不用再看着loading…………………………………………………

      今天中秋节,事情太多,加上环境不是很熟悉,实在处理不过来,今天就公司加班一天,上午把主要的事情处理了,下午来看看fastcgi相关信息,先来说cgi,再说fast-cgi。

一、cgi其实就是一个可执行的应用程序,apache在收到请求后交由你的这个应用来处理请求,如hello world来了

1
2
3
4
5
6
#include <stdio.h>
int main(){
    printf("Content-type:text/html\n\n");
    printf("Hello World\n");
    return 0;
}

编译一下:gcc hello.c -o hello;自己也可以测试一下 ./hello看看是否能正常打印
再把这个文件拷贝到 cgi-bin的目录,具体应该看apache配置 http.conf中站点的 ScriptAlias目录指定的地方

然后访问一下 http://站点域名/hello 看看是否正常输出了

这就是cgi,很简单吧,cgi不限制语言开发,装B的都是用C/C++,好像装。


那么什么是fastcgi呢,我去,随便找个hello你就啊,用个while包了一下cgi就是fastcgi,本想多高级,结果while都需要自己写,注意,hello来了。

http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/ch2c.htm

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <fcgi_stdio.h>
using namespace std;
int main(void){
    while(FCGI_Accept() >= 0){
        printf("Content-type: text/html\r\n");
		printf("hello world!");
    }
    return 0;
}

因为环境不好,没有测试,但我猜测是可以的,编译加入-lfcgi就可以了,至于cgi头文件..
下午看了一下内部的一个cgi的简单框架,写的很不错,也很简单,模板引擎用的是clearsliver (www.clearsilver.net/docs/c_api.hdf),其它过程就跟PHP扩展差不多过程,什么RINIT\MINTI之类的,业务只需要继承后写接口代码就行了。

顺便说一下再整个的学习过程中发现的两个点
1、在.h文件中加入 #pragma once 可以防止被多次加载,和编译环境有关系,普通的做法就是使用 #ifndef #define #endif;有点麻烦
2、#pragma pack() 例如:

1
2
3
4
5
6
#pragma pack(1) 
struct sample{
    char a;
    double b;
};
#pragma pack()

注:若不用#pragma pack(1)和#pragma pack()括起来,则sample按编译器默认方式对齐(成员中size最大的那个)。即按8字节(double)对齐,则sizeof(sample)==16.成员char a占了8个字节(其中7个是空字节);若用#pragma pack(1),则sample按1字节方式对齐sizeof(sample)==9.(无空字节),比较节省空间啦,有些场和还可使结构体更易于控制

glog初始化的一些方法,其中如果要实时flush日志,可以设置FLAGS_logbufsecs=0;

1
2
3
    FLAGS_logbufsecs = 1;
    google::InitGoogleLogging("");
    google::SetLogDestination(google::GLOG_INFO, "./xxx.log.");

glog 不支持按天轮转日志,所以需要对glog源码做一些修改,修改如下

修改 src/logging.cc文件,第913行(LogFileObject::Write开始之前)加上如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/***************CHANGE LOG BY DAY*************/
int _now_day = 0;
bool DayHasChanged(){
    time_t tt;
    time(&tt);
    struct tm *p;
    p=localtime(&tt);
    if(_now_day != p->tm_mday){
        _now_day = p->tm_mday;
        return true;
    }
    return false;
}
/********************************************/
 
//再修改LogFileObject::Write方法中判断语句加入
if (static_cast<int>(file_length_ >> 20) >= MaxLogSize() ||
      PidHasChanged() || DayHasChanged()) {
16 / 05 / 2013 admin

      最近终于开始迈上了c++的编码历程,之前一直很遗憾不会写c++,刚开始写的很痛苦,无数次想放弃,后来写着写着就顺了,终于算入门了,这段时间也遇到了好多问题,终归解决毕竟刚写c++。

1、前两天遇到个问题cout不出来东西,搞了好久原来被cache了,最后改成 fprintf(stderr, “[msg] sendxxxx length:%d \n”, 123)解决;
2、很多时候前一秒打印一个值还在,后一秒就没了,原来是被释放了,终于学会了new一个内存块出来存值,但稍后一定要delete掉
3、申明两个属性,char xxx[123]; bool ooo; ooo默认为true,后来无缘无故变成了false,莫名其妙,找了半天,发现xxx溢出了
4、今天在做protobuf测试的时候,发现某些时侯只能解出一半的值,原来ParseFromString不能单纯传入 char*,下面给出例子

再做protobuf前需要生成对应的protobuf的h和cc文件,可以使用:protoc EsunMessage.proto –cpp_out=./ 生成到当前目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void print_ascii(char* data, int len){
    fprintf(stderr, "ascii:");
    for(int i=0; i<len; i++){
        fprintf(stderr, "%X, ", data[i]);
    }
    fprintf(stderr, "\n");
}
 
int test_protobuf(char* content){
    char* buf = "<DB><ZC><USERNAME>xxx</USERNAME><PASSWORD>888888</PASSWORD></ZC></DB>";
    std::string orderstr;
    Order order;
    HeadInfo* headinfo = order.add_headinfo();
    headinfo->set_msgid("500000");
 
    order.SerializeToString(&orderstr);
 
    //打印一下char*的16进制代码
    print_ascii((char*)orderstr.c_str(), orderstr.length());
 
    //解析刚序列化后的char* string(orderstr.c_str(), orderstr.length()) //故意的
    Order orderr;
    orderr.ParseFromString(string(orderstr.c_str(), orderstr.length()));
    ACE_DEBUG((LM_DEBUG, ACE_TEXT("test:[%s]\n"),orderr.headinfo(0).msgid().c_str()));
 
    return 0;
}
无标签信息 0 条
07 / 05 / 2013 admin

搭建svn服务器,有如下一些步骤(http://wiki.centos.org/HowTos/Subversion)
1、首先安装svn服务端:mod_dav_svn、svn客户端:subversion
2、修改svn配置文件/etc/httpd/conf.d/subversion.conf
DAV svn
#SVNParentPath /var/www/svn
SVNPath /var/www/svn/repos
# Limit write permission to list of valid users.
#
# Require SSL connection for password protection.
# SSLRequireSSL
AuthType Basic
AuthzSVNAccessFile /var/www/svn/repos/conf/authz #用户权限配置
AuthName "Authorization Realm"
AuthUserFile /etc/svn-auth-conf #svn认证用户列表,通过htpasswd添加
Require valid-user
#



3、添加svn用户 htpasswd -cm /etc/svn-auth-conf xxx #-c Create a new file,第一个用户-c,第二个用户就不用了
4、mkdir /var/www/svn; cd svn;创建svn的根> svnadmin create repos #创建svn路径问repos的根
> chown -R apache.apache repos #把repos宿主给apache
> service httpd restart #重启服务

5、更改用户权限/var/www/svn/repos/conf/authz[repos:/]
xxx = rw

问题1、svn mkdir http://192.168.50.81/repos/ace -m ‘ace’
svn: Can’t open file ‘/var/www/svn/repos/db/txn-current-lock': Permission denied
解决办法:chown apache:apache -R db

问题2、svn mkdir http://192.168.50.81/repos/ace -m ‘ace’
svn: Can’t make directory ‘/var/www/svn/repos/dav/activities.d': Permission denied
解决办法:mkdir dav; chown apache:apache -R dav/

如果想独立于apache存在可以使用svnserve -d -r /var/www/svn/repos 来开启服务,默认监听3690端口,可以通过–listen-port来指定

一、定时开机设置方法


1、设置电脑定时开机,开机启动后,按DEL,进入BIOS,然后选中 "POWER" 在电源窗口中找到"RESTORE ON AC/POWER LOSS"项,回车,然后通过方向键设置其值为"POWER ON"。
2、选中"RESUME ON RTC ALARM"并按回车,接着通过方向键设置其值为"ENABLE"
3、选中"RTC ALARM DATE"按回车依次设置即可
4、按F10保存重启

二、定时关机方法

      一般可能就用crontab来解决,但如果哪天突然某个机器临时不关呢,那么去掉crontab,再设置不是很麻烦,所以,我采用at设置任务。思路是这样,我在一台主机如50.71上设置crontab,每天早上给所有机器下达18:00关机任务。这里如果是批量操作所有机器就设计到一个远程的问题,就采用 ssh等价性来做,操作如下

1、在主机50.71的.ssh目录中生成登陆其他50.*主机的sshkey:ssh-keygen -t dsa #一直回车到底
2、把id_dsa.pub拷贝到其余所有机器的 .ssh目录下,如果没有目录则创建:mkdir .ssh; chmod 600 .ssh; cd .ssh/
3、同时在该目录生成cat id_dsa.pub > authorized_keys;
4、给两个key附权限:chmod 600 id_dsa.pub; chmod 600 authorized_keys

每天建立at任务的shell脚本如下

View Code SHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
 
for i in `cat server_list.txt`;  do
    if [ `expr substr $i 1 1` == "#" ]; then
        continue;
    fi
    echo "[`date '+%Y-%m-%d %H:%M:%S'`] start set:$i";
    ssh -tt $i << EOF
echo "init 0" | at "19:00"; 
at -l;
exit;
 
EOF
done

今天又碰到时间提前了8个小时的问题,是时区的问题,首先,修改时区:cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
修改了还是没有变化,还是装个ntp软件吧,使用 ntpdate 210.167.182.10直接同步时间即可

18 / 03 / 2013 admin

上一篇文章已经介绍过scribe的安装过程了,基本都没有什么问题,下面开始做一下scribe的测试,安装scribe源码目录中example示例中的README步骤操作,开启scribe:

./src/scribed examples/example1.conf

结果报错
./src/scribed: error while loading shared libraries: libboost_system.so.1.46.1: cannot open shared object file: No such file or directory
通过执行能找到libboost的so文件,google后原来需要加入到ld.so.conf文件

whereis libboost_system.so.1.46.1
//libboost_system.so.1.46: /usr/local/lib/libboost_system.so.1.46.1

操作如下,vi /etc/ld.so.conf,加入下面这句话后,执行 ldconfig使配置生效,再执行,一切正常

/usr/local/lib/libboost_system.so.1.46.1

进入example文件夹做测试:echo ‘hello’|./scribe_cat test发现错误
ImportError: No module named scribe
进入scribe源码目录下面的lib/py文件夹make,并且setup.py install,再执行发现还是同样的错误,用python2.6测试正常,估计是scribe_cat用python2.4执行了,打开scribe_cat可以看第一行,改成你自己的python2.6的路径即可。同样发现没有thrift包,进入thrift-0.9.0/lib/py安装

再执行,发现还是错误:ImportError: No module named fb303.FacebookService,进入thrift-0.9.0/contrib/fb303/py安装

14 / 03 / 2013 admin

      这两天可累着了,为了安装scribe和thrift花了好大的神啊,估计也是经验不足造成的,还好,终于安装完成,下面对安装过程中遇到的问题做一些记录吧。

      刚开始的时候觉得应该挺简单,兴冲冲的去http://thrift.apache.org/下载了安装包,编译,发现需要一大堆的三方包支持,然后就从头到尾开始安装,有的安装包对版本有要求,只能源码下载安装,花了好些时间。最后遇到某个什么包的时候没搞定,问同事ronggr,他说没装,不用java所以可以不用装这个包,蒙了,难道不是所有的包都要装吗?去官网看安装文档 http://thrift.apache.org/docs/install/,我了个去,失策,好吧,简单安装,很快搞定了。这就是thrift安装的全过程,没有太多难点
      接着去github下载了scribe,安装,配置还算顺利,make的时候遭了不少罪。

1、出错,usr/local/include/thrift/protocol/TBinaryProtocol.tcc: In member function ‘uint32_t apache::thrift::protocol::TBinaryProtocolT::writeI16(int16_t)’:
/usr/local/include/thrift/protocol/TBinaryProtocol.tcc:147: 错误:‘htons’ 的实参不依赖模板参数,所以 ‘htons’ 的声明必须可用

http://stackoverflow.com/questions/8402479/error-while-compiling-thrift-server

解决办法:因为 没找到,设置一下吧 bash CPPFLAGS=”-DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H”
./configure CPPFLAGS=”-DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H”

2、一个fb303的错误,原来需要去thrift包的thrift-0.9.0/contrib/fb303安装,还算快。

3、错误,file.cpp:248: 错误:‘class boost::filesystem::directory_entry’ 没有名为 ‘filename’ 的成员

解决办法:boost库不对,我安装的是最新版boost1.5,换成1.49.
thrift、fb303和scribe都依赖于boost的c++库,boost版本要求至少1.36以上,yum安装的是1.33.1
而在1.45开始(比如我用的是1.49),boost的filesystem版本从v2到v3,注意scribe只支持到v2,所以编译scribe的时候,需要设置一下 bash CPPFLAGS=”-DBOOST_FILESYSTEM_VERSION=2″
-DBOOST_FILESYSTEM_VERSION=2 参数只有在你的boost版本大于1.46的时候需要添加
CPPFLAGS=”-DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -DBOOST_FILESYSTEM_VERSION=2″

      到此三个问题解决了,在过程中遇到一个包被安装了2次,rpm -qa发现,原来是x86_64的和i386的,想卸载发下报错 通过man rpm,发现–allmatches应该可以解决这个问题.
最后 rpm -e –allmatches xxx.rpm搞定

      装完scribe后发现yum坏掉了(提示Yum Segmentation Fault (core Dumped) ),原来是libz库文件冲突了,修改如下:

rpm -q zlib zlib-devel
cp /usr/lib/libz.so.1.2.3 /usr/local/lib/
cd /usr/local/lib
ln -sf libz.so.1.2.3 libz.so
ln -sf libz.so.1.2.3 libz.so.1
yum clean all

      好久没有充电了,看看一些现下少接触的东西,昨晚看了一下关于html5离线app的问题,主要是说离线程序的更新问题,待实践后再做记录。

      前两天才试用微信的网页端,使用手机扫描页面二维码来登陆,抓包了一下,使用长连接来轮询login.weixin.qq.com接口,实现起来其实应该不难,用户打开页面后生成一个唯一id的二维码链接,手机端扫描后验证成功,向服务器发送认证通过请求,网页端请求到服务端认证通过予以登陆。盛大也提供了类似这样的快速登陆方式。就是对小网站的开发有点麻烦,还需要发布扫描认证工具。

      逛博客园的看见网易财经的一哥写的一篇文章中关于h1标签的处理方法,对于现在大部分网站都使用了图片作为网站的logo,这样就直接把图片给了h1标签,给图片加alt属性。这里有一篇文章:http://stackoverflow.com/questions/665037/replacing-h1-text-with-a-logo-image-best-method-for-seo-and-accessibility,下面给三个例子

      我们再来看看,我们网站和sina的截图对比一下,基本是一个妈生的
sina and 500.com
      大概了解了一下原因,是因为更改logo图片方便些,对于这个问题,我们看看搜狐、腾讯、网易财经是怎么解决的

1、搜狐:logo的css代码写在css文件,css文件有版本号,使用text-indent隐藏文字
2、腾讯:logo的css代码写在页面中,css文件有版本号,使用display隐藏文字
3、网易财经:logo的css代码写在css文件,css文件有版本号,使用display隐藏文字

      不过个人比较倾向腾讯的做法,更改logo不用为css单独发布版本号,减少维护。

12 / 11 / 2012 admin

      这段时间把EsunPHP搞了一下,然后发现自己的水平并未见增长,又想起以前面试被问及php执行过程,结果哑口无言。某天刷微博,看见国内php大牛推荐了两个网站,其中一个是 http://phpbook.sinaapp.com 译者翻译的很好,读过很受启发,打算自己写一写扩展,但考虑到本地环境大家共用不能老是restart http server,所以就在自己账户下源码安装一个,虽然没什么,但还是打算记录一下
1、http://httpd.apache.org/download.cgi 下载Apache HTTP Server 2.2.23 (httpd)

tar -xzf httpd-2.2.23.tar.gz
cd httpd-2.2.23
#undefined reference to `apr_array_clear'
./configure --prefix=/home/xxx/soft/bin --enable-mods-shared=most --with-included-apr
make
make install

接下来修改一下/home/xxx/soft/bin/conf/httpd.conf文件

NameVirtualHost *:30080
ServerName 192.168.0.237:30080
<Directory "/home/xxx/soft/html">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<VirtualHost *:30080>
DocumentRoot /home/xxx/soft/html
ServerName 192.168.0.237
</VirtualHost>
#自建一个conf.d文件夹
Include conf.d/*.conf

php我自己就懒得编译了,就用系统的把

cp /etc/httpd/conf.d/php.conf ./conf.d/
cp /etc/httpd/modules/libphp5* ./modules/
./bin/apachectl restart

无标签信息 0 条