2009年11月

Nginx的proxy_pass中使用动态主机名

如果应用的后台对应有很多服务器
我们想根据前台url中的某个标识来代理到后台的某个对应server上
也就是说proxy_pass指令中不能写死某个ip或者某个servername
而是需要根据某个值来对应某个servername
如:s1.test.com,s2.test.com都是后台的server
它们有对应的dns解析

在Nginx0.6.18版本之前
proxy_pass指令中的server是不支持使用变量的
不过,有人给打了一个patch,参见:
http://www.ruby-forum.com/topic/173585

在0.6.18后的新版本中
对应的server上是支持使用变量来构造某个server
不过还需要增加一个resolver指令
来指定dns服务器的地址

resolver 192.168.132.1


对应的反向代理就可以这么写了

location ~* /test/(\d+)/(.+)$
{
proxy_pass http://s$1.test.com:8001/$2?$args;
}



如果你的proxy_pass代理的是某个ip或者某个固定的servername
如下:

proxy_pass http://192.168.132.100:8001/$1;


或者

proxy_pass http://s.test.com:8001/$1;


那么即使在后面的url上有其它的变量,也是不需要配置resolver指令

附件是老版本的nginx的patch:
patch.unix.txt

Linux上编译nginx单独包

应用nginx的服务器有很多台
每台的os环境都不一样
而且还有32位的,64位的机器
以前每次升级nginx都很麻烦
一台一台服务器上去重新编译安装
于是,就想单独编译一个供passport使用的nginx独立包
把它依赖的zlib,pcre,openssl等都编译进去
这样,每次升级时,直接scp这个独立包到各服务器上就行了
当然,独立包也需要2个版本,分别对应32位和64位

首先编译各个依赖包,指定--prefix为/opt/nginx下,然后再编译nginx

./configure --prefix=/opt/nginx --with-http_stub_status_module --with-http_ssl_module --with-zlib=/opt/ysz/src/nginx/zlib-1.2.3 --with-openssl=/opt/ysz/src/nginx/openssl-0.9.8k --with-pcre=/opt/ysz/src/nginx/pcre-8.00 --add-module=../nginx-upload-progress-module --add-module=../nginx_test


配置完成之后,手工修改objs/Makefile文件
把libpcre.a libssl.a libcrypto.a libz.a ssl.h几个文件对应的路径给修改成/opt/nginx/lib下
之后再make && make install后,在本机启动nginx没有问题
但拷贝到某台服务器上启动时,报错

error while loading shared libraries: requires glibc 2.5 or later dynamic linker”


看来是因为编译的机器的glibc版本太高了
所以就到一台低版本的机器上重新编译
但是拷过去后,又出了以下错误

error while loading shared libraries: libcrypto.so.4: cannot open shared object file: No such file or directory


经查,发现是运行机器的libcrypto.so版本太高,是libcrypto.so.6,而ldd显示nginx依赖的是libcrypto.so.4
于是,在对应的/lib64目录下建个libcrypto.so.4的软链接就可以了
后来,在douyuan的指点下,用了另外一个办法来解决这个问题
直接修改nginx的二进制文件,找到libcrypto.so.4,把后面的.4给替换成\0\0就可以了
如果在vi里进行编辑,可以使用xxd这个命令以16进制文本格式编辑,之后再转换回去就行了

说话"雷人"的昕昕

上午,姥姥带着昕昕出去玩
下楼后,他又跑到垃圾箱旁边看一个小狗的尸体
姥姥就和他说:

你就在这看吧,别走了,我走了哦


这时,昕昕转过头去
看着姥姥,然后说:

你要再说我把你挂树丫上


真晕,不知道这话他是从哪里学来的
呵呵,这小子有时说的话还真雷人......

Nginx的alias

之前一直没有注意过Nginx中的这个alias参数
当要访问的url直接对应本机的某个path时
都是使用root来做处理的
有时候,某个url是从前端的反向代理一直代理过来
url的前面某个路径是虚拟的path,这样就需要先rewrite下

location ^~ /html/1/{
root /opt/test/html/;
rewrite "^/html/1/(.*)$" /$1;
break;
}


就是先把前面的/html/1给去掉,然后在本机的/opt/test/html/下寻找

今天才知道,其实alias就是干这个活的,直接这么用就ok了

location ^~ /html/1/{
alias /opt/test/html/;



看nginx的官方文档吧

alias
syntax: alias file-path|directory-path;
default: no
context: location
This directive assigns a path to be used for the indicated location. Note that it may look similar to the root directive, but the document root doesn't change, just the file system path used for the request.

For example:

location  /i/ {
  alias  /spool/w3/images/;
}
The request "/i/top.gif" will return the file "/spool/w3/images/top.gif".

It is possible to use variables in the replacement path.
The alias directive cannot be used inside a regex-specified location. If you need to do this you must use a combination of rewrite and root.



注意最后一段,alias不能适用于正则匹配
如果要在正则里使用,则只能用前面所说的rewrite和root了...

Apache和Nginx中虚拟URL

有时候,我们会有这样的需求
前台Client往Apache或Nginx上发一条请求,带上一定的参数
我们只要把该请求的url给记录下来留待以后分析用,而不需要其它任何的操作
那么其实我们可以虚拟一个这样的url,只要在access log中有记录就可以了
对于这样的虚拟url,web server匹配后会直接返回,而不会有任何的磁盘操作

对于Apache来说,只要开启了mod_alias模块,然后

Redirect 200 /j.gif


只要匹配到了j.gif,那么Apache就直接返回200或者404
而不需要再到对应的DoucumentRoot下去查找对应的文件了

对于Nginx来说,可以有2种办法
1.在loaction上直接return:

location ~ /j.gif
{
return 200;
}


这种方式,类似于Apache,直接返回200
2.使用empty_gif模块:

location ~ /j.gif
{
empty_gif;
}


该模块会直接在内存里返回给你一个1×1的空白图片
使用这种方式有个好处就是,它是一个正常的请求,所以会经过Nginx的所有的module操作
如果我们在Nginx里有自己的module需要做一些额外的处理
而且还需要在acceess log里记录该module的处理后的某个header时
就只能使用empty_gif模块了

Nginx中配置中间级CA证书

这段时间,在我的firefox3.5上访问passport的https页面
直接就出错了,如下:

passport.sohu.com 使用了无效的安全证书。 该证书因为其发行者证书未知而不被信任。 (错误码: sec_error_unknown_issuer


开始以为是我的Firefox的某个地方配置有问题,因为在IE里是正常的
直到另外一个同事的Firefox也出这个错时,我意识到可能是证书的配置问题

以前,前端server上跑的是Apache2,现在全部更换成了Nginx
查看了一下Nginx的配置后,发现Nginx没有配置ssl的中间证书
查看了Nginx的文档后,开始以为是配置ssl_client_certificate这个参数
后来在老大的点化下,发现了Nginx应该这样配置:

if you have a chain certificate file (sometimes called an intermediate certificate) you don't specify it separately like you do in Apache. Instead you need to add the information from the chain cert to the end of your main certificate file. This can be done by typing "cat chain.crt >> mysite.com.crt" on the command line. Once that is done you won't use the chain cert file for anything else, you just point Nginx to the main certificate file.


就是说,Nginx中是把那个intermediate.crt文件给合并到自己的server.crt证书后面即可

而在Apache2中,是在httpd-ssl.conf中增加一行,可参见“Apache和Nginx的SSL证书的生成及配置

SSLCACertificateFile "/usr/local/apache2/conf/intermediate.crt"



而且,还发现了一问题,intermediate.crt文件是跟随着证书的crt文件,每年更换一次的
如果只更换了server.crt,而没有更换intermediate.crt文件,在Firefox下还是会出错的
因此,每年更换证书,需要同时更新server.crt和intermediate.crt
对于VeriSign,可在
http://www.verisign.com/support/verisign-intermediate-ca/secure-site-intermediate/index.html
下载到中间证书的

所以,如果申请的是全球服务器的证书,那么一定需要安装这个中间证书(IE下似乎不用安装,也不会报错...),以构成一个证书链

An intermediate certificate is the certificate, or certificates, that go between your site (server) certificate and a root certificate.The intermediate certificate, or certificates, completes the chain to a root certificate trusted by the browser.

Memcached Client的序列化

如果我们需要往memcached中存储非基本类型的Object时

是需要对这个Object进行序列化的

不过,现在的memcached client都已经替你做了序列化和反序列化工作了

所以,我们在使用时,可以直接把Object传给它,让它来实现序列化和反序列化



比如,python的Client工具memcache.py中



折叠复制代码




  1. flags=0

  2. if isinstance(val, str):

  3. pass

  4. elif isinstance(val, int):

  5. flags |= Client._FLAG_INTEGER

  6. val="%d"% val

  7. # force no attempt to compress this silly string.

  8. min_compress_len=0

  9. elif isinstance(val, long):

  10. flags |= Client._FLAG_LONG

  11. val="%d"% val

  12. # force no attempt to compress this silly string.

  13. min_compress_len=0

  14. else:

  15. flags |= Client._FLAG_PICKLE

  16. file=StringIO()

  17. pickler=self.pickler(file,protocol=self.pickleProtocol)

  18. if self.persistent_id:

  19. pickler.persistent_id=self.persistent_id

  20. pickler.dump(val)

  21. val=file.getvalue()




可以看到,对于复杂的Object,它默认是调用cPickle来作为其序列化的工具的

当然,我们也可以在set之前,也可以使用marshal或其它的工具来自行序列化



java的spymemcached的Client库

 



折叠复制代码




  1. byte[]b=null;

  2. intflags=0;

  3. if(o instanceof String) {

  4. b=encodeString((String)o);

  5. } else if(o instanceof Long) {

  6. b=tu.encodeLong((Long)o);

  7. flags |= SPECIAL_LONG;

  8. .....

  9. } else {

  10. b=serialize(o);

  11. flags |= SERIALIZED;

  12. }




最后,它调用了serialize方法进行序列化的,再看serialize方法

 



折叠复制代码




  1. ByteArrayOutputStreambos=newByteArrayOutputStream();

  2. ObjectOutputStreamos=newObjectOutputStream(bos);

  3. os.writeObject(o);

  4. os.close();

  5. bos.close();




Java的另外一个memcached client:java_memcached-release_2.0.1中是用URLEncoder进行了编码处理



折叠复制代码




  1. private String sanitizeKey( String key ) throws UnsupportedEncodingException    

  2. {   

  3.     return ( sanitizeKeys ) ? URLEncoder.encode( key, "UTF-8" ) : key;   

  4. }  






由于不同的Client实现的序列化方式不同,所以如果在不同的语言


如,java,python中使用同一个memcached来存取数据,可能会造成数据不一致的问题

烦人的昕昕

这几天晚上
昕昕都特别精神
以前,到了8点多钟
喝完奶粉后,他就困得不行了
躺在被窝里,一会就睡着了

但,最近几天晚上
喝完奶粉脱完衣服后
他躺在床上,精神的不得了
嘴里不停的在说话
没话他也自己找话说
把躺在她旁边的妈妈都困的不行了
可他就是睡不着
把宝宝妈妈折腾的哭笑不得

当然,我也被他折腾的好不到哪去
一打开电脑,他听到响声后
就爬了起来,嘴里嘟囔着:
爸爸在干什么活呢?我去看看....
说着就爬了过来
无奈,只好给关了

我想,那我就到客厅里去看书吧
搬了个小凳,打开灯刚坐下
昕昕就爬了起来,说:我要去撒尿(客厅里放了一个他的专用尿盆)
就跑了我边上,哪里是撒尿,分明是找我...
无奈,又被他给捉回去了....

就这么一直折腾,又怕他给冻感冒了
没办法就陪着他躺着
就这么耗着,快10点的时候,昕昕终于睡着了
不过,我也快该睡觉了...

在家里,只要他不睡觉
基本上,我和宝宝妈什么事都干不了
有时候真想把他送回老家去
但宝宝妈一直舍不得...

使用rsync+git来部署java代码

项目的版本控制切换到git后,相对于cvs来说,部署java程序有了一些问题
主要是因为:
1.cvs权限控制比较简单,只需要开个username,即可在服务器上update
   但是,我们用gitosis来管理权限,就需要把各服务器的公钥给传到gitosis上
2.cvs可以支持部分update,比如我们可以指定只update某个jsp
   但git是不可以的,pull下的就是最新的所有的代码,所以在pull之前一定要把更新内容给显示出来,便于确认

这样,我们需要写脚本,来完成从服务器上集中部署
大概有以下2种方案:
1.每个server上安装git,分配其只读的权限,从中央服务器上ssh到要部署的server上,并获取本次更新的文件,核心代码如下
  

ori_commit_id=`ssh root@$host "cd $module_path;git log -1 --format="%h""`
ssh root@$host "cd $module_path;git reset --hard;git fetch origin"
new_commit_id=`ssh root@$host "cd $module_path;git log -1 --format=\"%h\" origin/master"`
ssh root@$host "cd $module_path;git log --name-status --pretty=format:\"%ci %Cgreen%aN%Creset %s\" $ori_commit_id..$new_commit_id"


   这种部署方式,相对比较可靠,因为它直接ssh到server上,把该server本次更新的文件给列表了出来,确认后即可部署
2.在中央服务器上使用rsync来同步远程server的目录
  之所以用rsync是因为:scp和tar方式都无法来根据文件修改时间来确定要拷贝的文件,只能是全部覆盖或者每次修改部署脚本
  如果采用tar后再scp,那么所有文件都会被更新了,这样ant会把所有的src都重新编译一次,很麻烦的
  rsync的命令很简单,如下:
  

rsync -e ssh -tpogrv /opt/test/ --exclude=.git $host://usr/local/src/test


  注意需要后面的-t参数,它表明把文件的时间也给rsync到远程server上。
  -exclude表明是排除.git目录,主要是相对路径
  这种部署方式,相对比较简单,不需要为每个服务器开git权限
  但由于比较的版本是中央服务器的目录,所以必须保证远程服务器的版本和中央服务器的版本相同,否则可能会有问题的

Msysgit优化

快捷键:
Alt+Space+E+K: 选择文字,拷贝
Insert: 粘贴文字
Alt+Back: 删除到前一个空格
Ctl+Back: 删除之前的所有文字


设置alias
git config --global alias.l 'log -n 10 --format="%h %ci %Cgreen%aN%Creset %s %n"'


查看2个版本之间修改的文件列表
git log --name-status --pretty=format:\"%ci %Cgreen%aN%Creset %s\"  1258e..a3584

最新文章

最近回复

  • feifei435:这两个URI实际是不一样的
  • zsy: git push origin 分支 -f 给力!
  • 冼敏兵:简单易懂,good fit
  • Jack:无需改配置文件,看着累! # gluster volume se...
  • Mr.j:按照你的方法凑效了,折腾死了。。。。
  • zheyemaster:补充一句:我的网站路径:D:\wamp\www ~~菜鸟站长, ...
  • zheyemaster:wamp2.5(apache2.4.9)下局域网访问403错误的...
  • Git中pull对比fetch和merge | 炼似春秋:[…] 首先,我搜索了git pull和git fe...
  • higkoo:总结一下吧, 性能调优示例: gluster volume s...
  • knowaeap:请问一下博主,你维护的openyoudao支持opensuse吗

分类

归档

其它