UP | HOME

原创 2013年

Table of Contents

游戏充值对接小结

#+BEGIN_HTML
1. 接口参数严格的校验
2. 脏数据的及时发现和处理
3. 接口之间的信任度
4. 数据的反查及核对

可惜,如果直接数据库操作呢?咋办!估计只能权限的控制及回收了!

2013.11.13 push
#+END_HTML

工作失误反省 Redis并发问题

#+BEGIN_HTML
Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,
Redis对于多个客户端连接并不存在竞争,但是客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,
这些问题均是由于客户端连接混乱造成。

解决方法:
1.客户端角度,为保证每个客户端间正常有序与Redis进行通信
2.服务器角度,利用setnx实现锁。
3.计数器

2013.09.27 push
#+END_HTML

perl自动登陆ssh, 嘿嘿

#+BEGIN_HTML
最近一堆服务器帐号,有时候又需要登陆看看,像我这种记性不好又懒的人,总想做个自动登陆的东西,于是通过找找资料,自己摸索写了一个。

首先,建一文件 server_list.txt  输入内容如下

#ip地址 端口 账号 密码 备注唯一
192.168.0.221 22 root kg2013 localtest
192.168.0.222 32200 root kg2013 localtest2

然后写perl脚本 如下:
#!/usr/bin/perl
# mysshlogin模块 还需完善下一步可增加密码加密重新保存文件
# perl mysshlogin.pl -s localtest[文件备注项] 自动登录
# perl mysshlogin.pl -l 查看账号列表
# 请先安装 cpan install IO::Stty 及 cpan install Expect
# @author josephzeng | josephzeng36@gmail.com | 01 九月 2013 22:58:40
use strict;
use warnings;
use Expect;

my $argv_length = 0;
$argv_length = $#ARGV + 1;
if($argv_length<1){
    print "输入参数错误";
    exit;
}

my $server_list_file = 'server_list.txt';
open SERVERFILE, "< $server_list_file";
my @params;

my @line=;
close(SERVERFILE);

if($ARGV[0] =~ /-l/){
    print @line;
    exit;
}
if($ARGV[0] =~ /-s/){
    foreach my $var (@line){
        @params = split(/ /, $var);
        if($#params + 1 == 5){
            if($ARGV[0] =~ /-s/){
                if($params[4] =~ /$ARGV[1]/){
                    &ssh_connect("\@params");
                }
            }       
        }
    }
}

sub ssh_connect() {
    my ($host, $port, $user, $passwd);
    ($host, $port, $user, $passwd) = @params;
    my $exp     = new Expect;
    my $command = "ssh -l $user $host -p $port";
    $exp->spawn($command) or die "Cannot spawn $command: $!\n";
    my $pass = $exp->expect( 6, 'connecting' );
    $exp->send("yes\r\n") if ($pass);
    $pass = $exp->expect( 6, 'password' );
    $exp->send("$passwd\r\n");
    $exp->interact();
}

基本实现,不好的是,容易暴露帐号密码,下一步写个直接用加密过的密码,然后再把perl脚本加密。

2013.09.02 push
#+END_HTML

memcached > 1M 咋办呢?

#+BEGIN_HTML
今天做接口的时候,缓存是采用Memcached的,潜意识的记得 Memcached存储单个item最大数据是在1MB内。
那大于1M的数据咋办,总不至于现在要我换成采用redis吧?于是google了相关的一些知识,看到了一段这样的记录。
今天(2012-03-16)我们重新测试了memcached ::set的数据大小。可能是我们用php的memcached扩展是最新版,set数据的时候是默认压缩的。set 数据:

$ac = new memcahed();  
$data = str_repeat('a', 1024* 1024); //1M的数据  
$r  =  $ac->set('key', $data, 9999);  
//或者  
$data = str_repeat('a', 1024* 1024*100);//100M的数据  
$r  =  $ac->set('key', $data, 9999);  
不论是1M的数据还是100M的数据,都能set成功。后来我发现,memcachedset数据的时候是默认压缩的。
由于这个这个是重复的字符串,压缩率高达1000倍。因此100M的数据压缩后实际也就100k而已。

当我设置:

$ac->setOption(memcahed::OPT_COMPRESSION,0); //不压缩存储数据。  
$data = str_repeat('a', 1024* 1024); //1M数据  
$r  =  $ac->set('key', $data, 9999);//1M的数据set不成功。  
也就是说memcached server不能存储超过1M的数据,但是经过客户端压缩数据后,只要小于1M的数据都能存储成功。

详情可以看http://blog.csdn.net/hguisu/article/details/6163621。

2013.07.24 push
#+END_HTML

memcached 满了

#+BEGIN_HTML
今天使用memcached的时候,set之后再get,发现都是flase,真够“邪门”。左右求救貌似还是如此,突然同事A说,是不是内存满了?
吓!验证果然如此,贴验证过程,防下次再犯!
[root@xiaozeng ~]# ps aux | grep "memcached"
www       6049  2.9  4.7 3799524 3152748 ?     Ssl  Jul06 418:20 /usr/local/memcached/bin/memcached -d -L -m 3072 -p 33210 -c 4096 -u www -t 16

[root@xiaozeng ~]# top -p 6049
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
 6049 www       15   0 3710m 3.0g  548 S  0.0  4.8 418:20.03 memcached

2013.07.15 push
#+END_HTML

python scp小工具

#+BEGIN_HTML
相信大家都有同感,每次开发项目测试的时候,本地修改完了放到测试服务器进行测试,
肯定会为每修改一次就要手动更新到测试服务器进行测试感到烦躁等。
抽了点时间自己写了个python scp使用,减轻了这种烦躁。不多说,贴代码:

# -*- coding:utf-8 -*-
#!/usr/bin/python2.7
'''
@author josephzeng 水哥
2013-06-27
使用前 请先安装pexpect
每次写代码要手动更新文件进行测试
每次使用scp都要输入密码
索性定义全部服务器ip及帐号密码
然后将 python myscp.py 72 vip 或其他绑定到vim
测试环境 python2.7
'''
import sys
import pexpect

#可进行同步的列表
scp_todo_lists = {
        #key 唯一
        '72-vip':{
            #远程机器
            "scp_host":"",
            #端口号
            "scp_port":22,
            #scp帐号
            "scp_name":"",
            #scp密码
            "scp_pass":"",
            #同步的跟目录 远程
            "scp_base_dir":"/test/",
            #同步的跟目录 本地
            "local_base_dir":"/test/",
            #需要同步的子目录
            "scp_dirs":["py/"]
            }
    }

def funcSwitchDoit(ip, project):
    ''' 选择业务 '''
    ip = ip.lower()
    project = project.lower()
    key = ip+"-"+project
    funcScpDoit(key)

def funcScpDoit(key):
    ''' 生成同步命令 '''
    if scp_todo_lists.get(key):
        data = scp_todo_lists.get(key)
        scp_host = data.get('scp_host')
        scp_port = data.get('scp_port')
        scp_name = data.get('scp_name')
        scp_pass = data.get('scp_pass')
        scp_dirs = data.get('scp_dirs')
        scp_base_dir = data.get('scp_base_dir')
        local_base_dir = data.get('local_base_dir')

        if len(scp_dirs)>0:
            for item in scp_dirs:
                scp_cmd = "scp -rp "+str(local_base_dir)+str(item) + " -P "+str(scp_port) + " "+str(scp_name) + "@" + str(scp_host)
                scp_cmd = scp_cmd + ":"
                item_cmd = scp_cmd+str(scp_base_dir)+""
                funcScpCmd(item_cmd, scp_pass)
    else:
        print "sorry key is not in todo lists!"

def funcScpCmd(cmd, pwd):
    ''' 进行同步 '''
    try:
        try:
            child = pexpect.spawn(cmd)
            res = ['password: ', 'continue connecting (yes/no)?']
            id = child.expect(res)
            if 0 == id:
                child.sendline(pwd)
            elif 1 == id:
                child.sendline('yes')
        except pexpect.EOF:
            child.close()
            print "pexpect except!"
        else:
            res = child.read()  
            child.expect(pexpect.EOF)  
            child.close()  
            print res  
    except Exception, e:
        print "execpt ",e

if __name__ == "__main__":
    ''' 执行 '''
    params = sys.argv
    ip = None
    project = None
    if len(params) < 3:
        print "params fail!"
    else:
        ip = str(params[1])
        project = str(params[2])
        funcSwitchDoit(ip, project)

接下来,肯定是测试下了

[xiaozeng@localhost py]$ python2.7 myscp.py 72 vip

fetchall.py                                   100%  321     0.3KB/s   00:00    
.project                                      100%  362     0.4KB/s   00:00    
re.py                                         100% 1074     1.1KB/s   00:00    
sockser.py                                    100%  520     0.5KB/s   00:00    
org.eclipse.core.resources.prefs              100%   56     0.1KB/s   00:00    
sockclient.py                                 100%  413     0.4KB/s   00:00    
walk.py                                       100%  243     0.2KB/s   00:00    
thread.py                                     100%  504     0.5KB/s   00:00    
yield.py                                      100%  204     0.2KB/s   00:00    
myscp.py                                      100% 2803     2.7KB/s   00:00

当然,这个小工具还需要完善,可以结合ssh 进行检测是否存在目录进行新建,然后进行同步。

至于你是否绑定到自己的编辑器里或放到定时任务里,那就自己喜欢了。

2013.06.28 push
#+END_HTML

DNS轮询负载均衡

#+BEGIN_HTML
公司的某个项目是采用DNS轮询负载均衡的。当然,大家都知道,采用DNS轮询负载均衡的成
本是相当底的,又或该项目都是一些静态页面。但是用过DNS轮询负载均衡的人都知道,DNS负载均衡存在明显的缺点,
一是可靠性不高,二负载分配不均衡。这里为了实现静态化页面,是采用了某台机器定时运行脚本生成的,然后同步多台机器的。
说到这里,你就会发现有问题了,当在生成脚本那个时间段,某台机器的压力肯定是比较大或过大的,然后生成了静态页面后,
同步又是否会出问题呢?这些问题就比较难说了,都是需要考虑进去的。就算上面的一切问题都正常,然而定时生成的静态页面,
估计至少会有30%的页面是无人访问又或访问量及底的,这样的话,又算不算浪费了一部分资源呢?当然,如果不考虑成本的话,
相信都会直接采用lvs架构的。其实,如果采用nginx反向代理结合apache会不会也是一种好的选择呢?未知数……

2013.06.23 push
#+END_HTML

Date: 2014-08-29

Author: josephzeng

Created: 2014-10-31 周五 13:19

Emacs 24.4.1 (Org mode 8.2.10)

Validate