服务影响时间测量

这几天配置dns集群,为了测试各种场景下的服务影响时间,需要自己写个脚本进行统计。没有什么现成的好的工具,就用python里面的dnspython模块写了个小的脚本
[python]
#!/usr/bin/python
#****************************************************************#
# ScriptName: dnsquery.py
# Author: GNUer
# Create Date: 2013-06-28 12:52
# Modify Author: GNUer
# Modify Date: 2013-06-28 12:52
# Function:
#***************************************************************#
import dns.resolver
import dns.exception
import time
import datetime
import signal
import sys
def get_time():
t=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return t
def get_mtime():
t=datetime.datetime.now().strftime("%H:%M:%S.%f")
return t
def get_second():
return time.time()
def do_exit(sig,arg):
print "exit dns test"
sys.exit(1)
def dns_test(num,sleep_time):
resolver = dns.resolver.Resolver()
#resolver.timeout = 0.01
resolver.lifetime =0.0013
#change this time accord to reponse time
resolver.nameservers=[‘7.7.7.7′,’6.6.6.6’]
testlist=("search.xxx.com","obs.xxx.com","if.xxx.com")
last_flag=True
fail_start=0
fail_finish=0
for i in range(num):
for test in testlist:
try:
for target in resolver.query(qname=test):
print "\x1b[32m",get_time(),test,target,"\x1b[m"
if last_flag == False:
last_flag= True
fail_finish=get_second()
errortime=fail_finish-fail_start
print "\x1b[1;31m","error time is:",errortime,"\x1b[m"
except dns.exception.Timeout:
print "\x1b[31m",get_time(),test,"failed","\x1b[m"
if last_flag == True:
fail_start=get_second()
last_flag = False
time.sleep(sleep_time)
signal.signal(signal.SIGINT,do_exit)
dns_test(10000000,0.33)
[/python]
需要比较注意的是需要根据自己的实际情况把resolver.lifetime设置为比dns服务器的响应时间稍微大一点的值,但是需要小于平均响应时间的2倍。不然测试的时间不是太准确。因为总共测试的域名是3个,所以我把每次sleep的时间设置为0.32左右,使得1s总共能发3个请求左右。
测试的时候可以先把这个脚本一直跑着,然后去做各种操作,看中间的影响时间是多少。虽然这个脚本是测试dns的,但是也可以修改一下做HTTP请求等等,方便在做各种HA切换的时候测试影响的时间。

发表在 python | 留下评论

配置nginx不暂存服务端的响应到缓冲区

nginx做代理的服务器的时候是默认等后端服务器完成响应后再一次把内容返回给用户。这个关键的配置项目是proxy_buffering.
proxy_buffering 默认是on

This directive activate response buffering of the proxied server.
If buffering is activated, then nginx reads the answer from the proxied server as fast as possible, saving it in the buffer as configured by directives proxy_buffer_size andproxy_buffers. If the response does not fit into memory, then parts of it will be written to disk.

If buffering is switched off, then the response is synchronously transferred to client immediately as it is received. nginx does not attempt to read the entire answer from the proxied server, the maximum size of data which nginx can accept from the server is set by directive proxy_buffer_size.

Also note that caching upstream proxy responses won’t work if proxy_buffering is set to off.
For Comet applications based on long-polling it is important to set proxy_buffering to off, otherwise the asynchronous response is buffered and the Comet does not work.

Buffering can be set on a per-request basis by setting the X-Accel-Buffering header in the proxy response.
对于有的应用是有服务端自己推送数据的,需要把proxy_buffering设置为off,不然达不到预想的效果。

发表在 nginx | 留下评论

一次ssh信任登录失败的排查

昨天遇到有同事帮忙看一下信任登录打通的问题,已经把跳板机的公钥加到服务器上了,但是每次登录都要输入密码。
ssh -v看了一下
能成功登录的机器是
debug1: Next authentication method: publickey
debug1: Trying private key: /home/admin/.ssh/identity
debug1: Offering public key: /home/admin/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 277
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
不能成功登录的机器是
debug1: Next authentication method: publickey
debug1: Trying private key: /home/admin/.ssh/identity
debug1: Offering public key: /home/admin/.ssh/id_rsa
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Trying private key: /home/admin/.ssh/id_dsa
debug1: Next authentication method: password
区别是不能成功登录的服务器没有接受到私钥。查看一下是.ssh整个目录的宿主uid是有问题:
# stat .ssh
File: “.ssh”
Size: 4096 Blocks: 8 IO Block: 4096 目录
Device: ca20h/51744d Inode: 311305 Links: 2
Access: (0755/drwxr-xr-x) Uid: ( 500/ UNKNOWN) Gid: ( 500/ XXX)
Access: 2013-06-15 23:04:15.000000000 +0800
Modify: 2013-04-03 11:24:29.000000000 +0800
Change: 2013-06-15 23:04:15.000000000 +0800

用户的UID其实不是500,但是.ssh的UID却被设置为了500,chown xxx:xxx .ssh -R后解决。

发表在 System | 留下评论

指定dns查询的超时时间

最近在做些打杂的事情,需要对dns做一下健康检查。脚本直接shell写的,以前的同事的方案只是直接检查一下named进程是否存在,存在就是表示OK的,这个策略显然是有问题的,比如进程假死之类的其实是没有办法检查的。然后我就想着改成nslookup或者host命令进行一个查询,检测返回值,由于nslookup的返回值不能体现出查询是否成功,就只有host可以用了。
[bash]
check_dns(){
local domain
local server
domain="www.xxx.com"
server=’127.0.0.1′

host -W1 $domain $server &>/dev/null
error=$?
if [ $error -ne $STATUS_OK ];then
warn "can’t resolve $domain,error."
fi
return $error
}
[/bash]
但是使用host的话,如果DNS服务器hang住了,即便自己设置了每次wait的时间是1s,总的也需要等6s才能完成检查。这个检查的发现时间是太长了,所以改成了使用dig来做。
[bash]
check_dns(){
local domain
local server
domain="www.xxx.com"
server=’127.0.0.1′
dig @$server $domain +time=1 +retry=1 +tries=1 &>/dev/null
error=$?
if [ $error -ne $STATUS_OK ];then
warn "can’t resolve $domain,error."
fi
return $error
[/bash]
这样每次检测的超时时间就只有1s,每次只进行一次查询,重试的最大次数1次。基本能满足需求

发表在 OS | 留下评论

gnome-terminal的常用快捷键

平时很山使用快捷键什么的,主要是经常记不住。不过现在买了个机械键盘就是为了多试试用快捷键提高自己的日常的操作效率(其实主要是不能用小红点了。。。)。
刚看下了,其实gnome-terminal自己也带了很多常用的快捷键。
我自己单独定义了一个期待term的快捷键是ctrl+alt+t.
gnome-terminal的快捷键主要有:
新建一个标签页:ctrl+shift+t
新建一个窗口:ctrl+shift+n
多个标签页的切换可以有2种方式:
1.使用alt+数字N 直接切换到第N个标签页。
2.使用ctrl+pageup/pagedown做前后的切换
关闭一个标签页:ctrl+shift+w
关闭整个窗口:ctrl+shift+q

发表在 linux shell | 留下评论

vichrome插件使用

今天买了个机械键盘,不过买了机械键盘后第一个感觉是之前用习惯了小红点现在非常不习惯。之前小红点完全可以代替鼠标的很多操作,现在却是很多操作需要另外去用鼠标才能搞定。想起了之前有个浏览器的vi插件就装了下。不过很久没有用这个玩意了早就忘记了。
主要需要记住的操作是:
t 打开新的标签页
o 在当前的表情页打开新的url
ctrl+u 向上一页
ctrl+d 向下一页
上下左右和vim里面一样的k/j h/l
ctrl+h转向左边的标签页
ctrl+l转向右边的标签页
/ 搜索
[text]
Vichrome’s default key bindings are:

j : scroll down
k : scroll up
h : scroll left
l : scroll right
<C-e> : scroll down
<C-y> : scroll up
t : open new tab
x : close tab
X : Close the current tab and focus the previous tab
r : reload tab
/ : enter search mode
? : enter backward search mode
a : enter link text search mode(search only text that have a link and focus it)
n : next search result
N : previous search result
gg : go to top of the page
G : go to bottom of the page
gt, <C-h> : move to left tab
gT, <C-l> : move to right tab
H : back history
L : forward history
u : restore last closed tab
gp : pop out current tab to new window
gs : open source of the current page in a new tab
f : enter f Mode (like HIT-A-HINT)
F : enter f Mode (open links with new tab)
i : focus on first input area
o : Open new page with awesome completion
O : Open new page in new tab with awesome completion
s : Google Search
S : Google Search in new tab
b : Open bookmark
B : Open bookmark in new tab
<C-f> : page down
<C-b> : page up
<C-d> : page half down
<C-u> : page half up
: : enter Command Mode
” : back to last auto page mark
yy : copy URL to clipboard
p : Open a URL based on the current clipboard contents in the current tab
P : Open a URL based on the current clipboard contents in a new tab
<C-^> : switch tab focus to the previously focused tab
,z : toggle image size
<ESC> : cancel all input/command and blur focused element
[/text]

发表在 Admin | 留下评论

页面元素检测脚本

我们经常遇到某个页面缺少一个js之类的情况,一般使用firefox的httpfox或者chrome自带的工具都可以查看那些元素有问题.用python写了一个脚本,分析页面里面引用的元素,然后逐个进行请求,查看是否有的元素不能成功获取.不过使用urllib2有的地方异常处理也做的不完善,目前只是自己简单测试了一些,当熟练一下Python的用法了.目前从perl切换到python还是有很多的地方不是太习惯.尤其是很多列表和字符串的操作有点不一样.
[python]
#!/usr/bin/env python
import urllib2
import gzip
import binascii
import re,sys
import string
from StringIO import StringIO
def gunziptxt(data):
buf = StringIO(data)
of =gzip.GzipFile(fileobj=buf,mode="rb")
outdata=of.read()
return outdata
def http_code(url):
request=urllib2.Request(url,headers={‘User-agent’:"python urllib browser","Accept-Encoding":’gzip’})
try:
response=urllib2.urlopen(request,timeout=5)
return response.getcode()
except urllib2.HTTPError,error:
print "url:",error.reason
return error.code
except urllib2.URLError,error:
print url,error.reason
return 1000
def http_client(url):
request=urllib2.Request(url,headers={‘User-agent’:"python urllib browser","Accept-Encoding":’gzip’})
try:
response=urllib2.urlopen(request,timeout=5)
info=response.info()
data=response.read()
except urllib2.HTTPError,error:
print "%s error:%s" %(url,error.reason)
return None
except urllib2.URLError,error:
print error.reason
return None

if info.get("content-encoding",None) == ‘gzip’:
outdata=gunziptxt(data)
else:
outdata=data
return outdata
def get_src(page):
src_re=re.compile(r’src\s*=\s*["|\’]\s*(https?://[^\"\’]+?)["|\’]’)
if page:
link_urls=src_re.findall(page)
return set(link_urls)
else:
return set()
if len(sys.argv)<2:
print "usage:\n\t",sys.argv[0],"url"
exit(1)
if __name__ == "__main__":
urls=sys.argv[1]
pages=http_client(urls)
if pages:
links=get_src(pages)
else:
exit(1)
for link in links:
code=http_code(link)
if code >399:
print "%s \x1B[1;31m%d\x1B[m"%(link,code)
else:
print "%s \x1B[1;32m%d\x1B[m"%(link,code)
else:
print "pagecheck test"

[/python]
用法比较简单:
python pagecheck.py ‘http://www.baidu.com’

发表在 python | 留下评论

python多线程测试

仿照之前自己写的一个perl的多线程的脚本,简单试了下python的多线程模块threading.只能说因为之前习惯了perl的很多用法,刚切换到python非常不习惯,一些小的操作上不熟练.


#!/usr/bin/env python
import threading
import time
import random
import sys
import string
def fun_test(x):
    sleep_time=random.random()*1
    print "args is %s sleep time is %.4f s" % (x,sleep_time)
    time.sleep(sleep_time)
def multi_do(lists,concurrent_max,func):
    concurrent=0
    thread_list=set()
    while( len( lists ) &gt; 0 ):
        if len(thread_list) &lt;= concurrent_max:
            ser=lists.pop()
            pid=threading.Thread(target=func,name=ser,args=(ser,))
            thread_list.add(pid)
            pid.start()
        else:
            alive_threads=set(threading.enumerate())
            join_threads=thread_list-alive_threads
            for job in join_threads:
                print "%s is done"% job.getName()
                job.join()
                thread_list.remove(job)
    while(len(thread_list)&gt;0):
        alive_threads=set(threading.enumerate())
        join_threads=thread_list-alive_threads
        for job in join_threads:
            print "%s is done"% job.getName()
            job.join()
            thread_list.remove(job)
    print "all job have been done"
if __name__ == "__main__":
    try:
        fd=open(sys.argv[1],"r")
        print "open %s ok" % sys.argv[1]
        todo_list=fd.readlines()
        todo_list=map(lambda x: x.strip(),todo_list)
        print "to do is:\n","\n".join(todo_list)
    except IOError:
        print "open file failed"
    fd.close()
    multi_do(todo_list,10,fun_test)
发表在 python | 留下评论

设置TIME_WAIT的目的

设置TIME_WAIT的两个原因是:
1.实现了全双工的TCP连接关闭。
TIME_WAIT会出现在主动关闭这端的原因是:该端发出最后一个ACK后,如果这个ACK丢失或最后一个FIN丢失,另外一段将会超时重传最后的FIN。主动关闭这端由于TIME_WAIT的存在可以在需要的时候重传最后的确认报文,否则它收到最后的FIN后可能无法重传最后的ACK,而只能发出RST。另外TIME_WAIT总是从收到最后一个FIN开始算起,当它收到对端重传的FIN后会重新计时。
2.过时的重复报文段失效
每个IP数据包的有效时间由TTL(长度定义为8bit,所以最多经过的路由次数是255)限制。MSL定义为报文的最大生存时间,Linux下是30s。每个连接的新的替身只能在2MSL后才能再次发起,主要是为了保证前一个连接的过时重复报文段不会在新的连接出现,保证不会被误认为是第二次连接的报文段。

发表在 net | 留下评论

用python解压web服务器返回的gzip数据

之前用tcpdump抓包的时候,只要是gzip压缩过的数据就没有办法直接还原原始的数据。这段时间学了一下python正好看里面有gzip模块。今天先尝试了一下解压web server返回的压缩过的数据。测试了一下OK


#!/usr/bin/env python
import urllib2
import gzip
import binascii
from StringIO import StringIO
def gunziptxt(data):
    buf = StringIO(data)
    of =gzip.GzipFile(fileobj=buf,mode="rb")
    outdata=of.read()
    return outdata
url="http://127.0.0.1/index.html"
request=urllib2.Request(url,headers={'User-agent':"python urllib browser","Accept-Encoding":'gzip'})
try:
    response=urllib2.urlopen(request,timeout=5)
    data=response.read()
except:
    print "get %s response failed" %url
print "headers:\n",response.info()
if response.info()["content-encoding"] == 'gzip':
    print "http resonse is gzip"
    outdata=gunziptxt(data)
    lbuf=StringIO()
    with gzip.GzipFile(mode='wb',fileobj=lbuf) as inf:
        inf.write(data)
    gziplen=len(lbuf.getvalue())
    print "gzip %d and gunzip %d"%(gziplen,len(outdata))
else:
    print "http resonse is not gzip"
    outdata=data
print "http response:\n",outdata

要获取压缩过的数据的长度只能先借助StingIO,把原始的输出放进去后才能用len来得到。

发表在 python | 留下评论