PHP设计模式之-单例模式

归类于php | 设计模式 2 条评论

很多朋友学习接触设计模式的时候都是从单例模式、工厂模式等广泛应用的模式开始的,今天就来说说PHP的单例模式。

单例模式,也叫单子模式,使用这个模式时候,单例对象的类只能生成一个实例。恰是只能唯一生成一个类的实例对象在有的场合里面特别合适好用。比如:

  1. 系统的数据库连接对象的创建(创建多个对象既耗资源又不方便管理)
  2. 某个系统全局配置对象(同理)
  3. 系统统计模块对象(同理)
  4. 更多…

那么,一个单例类需要满足什么样的条件呢?

  1. 类的构造方法必须为私有的,即Private。(这样外部就不能通过new来创建多个实例了,我们而是通过使用一个公共的方法get_instance()得到该类的实例对象)
  2. 拥有一个保存该类实例对象的私有的静态属性$instance。(在上一步,私有构造函数执行后,把刚实例化的对象存储在这里,供get_instance()获得实例对象)
  3. 拥有一个对外获取该类实例对象的公共方法get_instance()。(对外获得单例类实例对象的公共接口)

那么按照上面这三个条件写出来的一个单例模式类如下(懒汉模式):

class singleton {

private static $instance = null;

private function __construct() {}

public static function get_instance() {

if (!self::$instance instanceof self) {
self::$instance = new self();
}

return self::$instance;
}
}
?>

单例模式的实现又有两种,懒汉模式饿汉模式,上面的DEMO代码示例就是懒汉模式的实现。
懒汉模式,即实例的初始化交给第一次使用的时候构建
饿汉模式,即实例的初始化在类的装载的时候就构建
下面也给出恶汉模式的实现:

class singleton {

private static $instance = new self();

private function __construct() {}

public static function get_instance() {
return self::$instance;
}
}
?>

注意:在多线程下使用单例模式的时候必须得特别小心,如果当唯一实例尚未创建时,有两个或多个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个或多个实例被构造出来,从而违反了单例模式中实例唯一的原则。理论上解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁,即我们可以把互斥锁加在singleton::$instance变量上,还好,PHP是单线程的,不知道模拟出来的多线程会造成单例模式的线程不安全么?以及其他语言天生就具备这样条件,比如JAVA的synchronized关键字.

使用rsync备份网站数据(1)

归类于Linux | rsync 一条评论

前天干了件吐血的大事,是这样的,同事让我帮他清理下服务器上一些乱七八糟的用户,我cat下/etc/passwd文件,里面一堆的用户乱七八糟的用户文件,更为可耻的是有人还把用户加入sudoers里面去了(之前接触过该台服务器的人),我二话不说,一个个使劲的删,连同用户所属的文件也通通删了(使用命令usrdel -f -r xxx,以后删除东西的时候千万千万要注意-f参数,最好任何时候都别用),包括一些FTP账户,FTP用户直接使用的是本地用户,自然FTP是用来管理网站程序的,于是我也把它删了,悲剧发生了,这些FTP账户所属目录就是网站程序文件,一删除用户资料带着程序文件全删除了,后来网站不能访问了检查一遍机器其他问题后才发现问题,当时都没反应过来,之后那个悔,那个慌。还好有备份,不过这两天的图片没了得重新上传。

于是,在这件事情的基础上,就决定配置一个实时性比较强的数据备份,自然用rsync。至于rsync是什么东东,同学们自己Google或者百度去。

Ubuntu Server,Centos,Debian等安装rsync服务可以直接使用在线安装包。


sudo apt-get install rsync


yum install rsync

安装好了之后,我们接下来需要配置三个文件,分别是rsyncd.conf、rsyncd.motd、rsyncd.secrets,这三个文件分别是主配置文件、显示欢迎界面文件以及密码验证文件,并且rsyncd.conf默认是不存在的,得自己创建。

touch rsyncd.conf

接下来,在该配置文件里写入如下配置代码:

# Distributed under the terms of the GNU General Public License v2
# Minimal configuration file for rsync daemon
# See rsync(1) and rsyncd.conf(5) man pages for help
# This line is required by the /etc/init.d/rsyncd script
pid file = /var/run/rsyncd.pid
port = 873
address = 192.168.1.1

#uid = nobody
#gid = nobody
uid = root
gid = root
use chroot = yes
read only = yes

#limit access to private LANs
hosts allow=192.168.1.2/255.255.255.0
hosts deny=*
max connections = 5
motd file = /etc/rsyncd.motd

#This will give you a separate log file
log file = /var/log/rsync.log

#This will log every file transferred - up to 85,000+ per user, per sync
#transfer logging = yes
log format = %t %a %m %f %b

syslog facility = local3
timeout = 300

[larro]
path = /var/www/larro
list=yes
ignore errors
auth users = root
secrets file = /etc/rsyncd.secrets
comment = This is the System file of Larro's Blog
exclude = easylife/ samba/

大概解释下上面的配置代码:
address =192.168.1.1 rsync服务器的IP地址
uid = root 使用root用户
gid = root 使用root用户组

注意:服务器端传输文件时,需要配置使用哪个用户和用户组来执行,默认是nobody。 如果用nobody用户和用户组,可能遇到权限问题,有些文件从服务器上拉不下来。偷懒为了方便,用了root ,或者也可以在定义要同步的目录时定义的模块中指定用户来解决权限的问题。

hosts allow=122.224.164.218/255.255.255.0
hosts deny=*
上面两行是指定那些客户端IP可以连接到该rsync服务器,这个配置能很大程度上提高安全性,host allow 是允许的IP列,格式为IP/网段,多个空格隔开

log file=/etc/log/rsync.log rsync的日志记录文件
以及,上面的rsyncd.conf配置文件是分为两部分,包括第一部分公共配置参数(上面解释部分)以及单个模块的配置,如上:

[larro]
path = /var/www/larro
list=yes
ignore errors
auth users = root
secrets file = /etc/rsyncd.secrets
comment = This is the System file of Larro's Blog
exclude = unrsync/

这里,是指配置了一个名为larro的同步备份项目模块:
path = /var/www/larro 是要备份的文件的位置

list = yes 参数是表示是否允许列出文件结构,一般不要配置成yes,因为这样别人就能知道文件结构了,多少是个不太安全的因素。
auth users = root 验证时候使用的用户
secrets file = /etc/rsyncd.secrets 验证时候使用的密码验证文件,就是上面提到的三个配置文件之一
comment = This is the system file of Larro’s Blog 这个是当你列出该项目模块时候的一个说明文字,可以任意配置
exclude = unrsync/ 配置项目模块里你不想同步备份的文件及文件夹,多个空格隔开
至此,rsyncd.conf配置文件弄好了,具体的其他详细配置项目在官方配置文档里查看,大家可仔细参考,接下来来配置rsyncd.motd,rsyncd.secrets.

rsyncd.motd也是可以任意配置,因为它仅仅是一个显示欢迎的话语,不过可以写得工整点,比如:

+++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Welcome to use the rsync +
+++++++++++++++++++++++++++++++++++++++++++++++++++++

然后配置rsyncd.secrets,前面rsyncd.conf里面使用的验证用户名是root,那么这里面配置的就是root的验证密码.

echo "mypasswod" > /etc/rsyncd.secrets
chown root /etc/rsyncd.secrets
chmod 600 /etc/rsyncd.secrets

听上去有点恐怖,太不安全了吧呵呵,这个配置文件权限必须是设置成600,不然无法使用rsync服务,到时候会提示以下错误信息:

password file must not be other-accessible
continuing without password file
Password:

这样子就没关系了,因为权限设置为600,也就是只有root用户本身才能读写,也就是说其他用户登录系统后,并不能查看到root的账户信息,不过前提是你是这样设置的并且rsync服务被你配置成功了,呵呵。
到这里,一个rsync服务器上面的简单配置就好了。
启动服务:

rsync --daemon --config=/etc/rsyncd.conf

上面命令是通过–daemon参数在后台启动rsync服务,并且通过使用/etc/rsyncd.conf配置文件来启动rsync服务,如果配置文件为默认的/etc/rsyncd.conf则可以不使用–config参数来指定配置文件位置。

然后你得弄另外一个机器192.168.1.2来备份上面机器项目文件。
一样,先安装rsync。
然后,使用下面命令测试下:

rsyncd --list-only root@192.168.1.1::larro

之后会提示输入密码,成功后会列出larro模块下所有的文件,或者通过在客户机上配置存放一个密码文件来访问,省得每次都提示输入密码,创建某个rsync账户的密码文件,比如上面用的root密码。

mkdir /etc/rsync
touch /etc/rsync/rsync.larro.passwd
echo "mypassword" > /etc/rsyc/rsync.larro.passwd

然后你就可以直接这样使用命令:

rsync --list-only --passwd-file=/etc/rsync/rsync.larro.passwd root@19\
2.168.1.1::larro

rsync有六种不同的工作模式:

  1. rsync [OPTION]… SRC [SRC]… [USER@]HOST:DEST
  2. rsync [OPTION]… [USER@]HOST:SRC DEST
  3. rsync [OPTION]… SRC [SRC]… DEST
  4. rsync [OPTION]… [USER@]HOST::SRC [DEST]
  5. rsync [OPTION]… SRC [SRC]… [USER@]HOST::DEST
  6. rsync [OPTION]… rsync://[USER@]HOST[:PORT]/SRC [DEST]

解释:

  1. 拷贝本地文件;当SRC和DES路径信息都不包含有单个冒号”:”分隔符时就启动这种工作模式。
  2. 使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST路径地址包含单个冒号”:”分隔符时启动该模式。
  3. 使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC地址路径包含单个冒号”:”分隔符时启动该模式。
  4. 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含”::”分隔符时启动该模式。
  5. 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含”::”分隔符时启动该模式。
  6. 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。

rsync中的参数

-a  以archive模式操作、复制目录、符号连接 相当于-rlptgoD

-r  是递归

-l  是链接文件,意思是拷贝链接文件;-p 表示保持文件原有权限;-t 保持文件原有时间;-g 保持文件原有用户组;-o 保持文件原有属主;-D 相当于块设备文件;

-z  传输时压缩;

-P  传输进度;

-v  传输时的进度等信息,和-P有点关系,自己试试。可以看文档;

-e  ssh的参数建立起加密的连接。

-u  只进行更新,防止本地新文件被重写,注意两者机器的时钟的同时

--progress  是指显示出详细的进度情况

--delete  是指如果服务器端删除了这一文件,那么客户端也相应把文件删除,保持真正的一致

--password-file=/password/path/file  来指定密码文件,这样就可以在脚本中使用而无需交互式地输入验证密码了,这里需要注意的是这份密码文件权限属性要设得只有属主可读。

在这篇文章里就先讲讲rsync的基本配置,在下一篇写写怎么通过rsync、crontab、shell来完成备份同步服务器上数据文件。

// -_-  Larro

使用/proc虚拟文件系统查看优化WEB程序

归类于CGI/FastCGI | Linux | Nginx 参与评论

在服务器上,我们一般使用top命令工具来监视服务器进程和Linux整体性能。

top

将会看到如下结果界面:

会列出了进程PID,USER(所属用户),PR,%CPU,%MEM,COMMAND(命令或者服务)等参数的列表,这个显示列表是动态跟踪服务器的。
问题来了,在上面的监控中,主要查看$CPU,%MEM,COMMAND这几个参数值,上面可以看到排在前面的两个进程都肚子占用了一枚CPU的%100。另外也可以根据这个列表看出WEB服务器有多少个CPU,数数php5-cgi的行数就是了。

看到两个php-cgi进程貌似是因为程序存在问题死循环什么的了把当时处理这个脚本的CPU给占满了,在这里,虽然我们大概知道是程序某个地方存在严重的问题,但是我们不能具体定位出来到底是系统的哪段文件出问题了。

于是,/proc来帮我们了,我们找到哪个进程在耗CPU,

对,PID为24207和24219这两家伙,咱们来用/proc虚拟文件系统来定位吧。

ls -l /proc/24219 # 后面的数字为上面的PID

注意上图中蓝色的路径,对,这个路径就是此段程序执行的代码路径,定位到了吧,然后你就可以在这个路径下去找那原因了

服务器流量监控工具-bmon

归类于Linux | Nginx 参与评论

介绍一款服务器流量监控工具,Bmon,在Linux社区也比较常用,它提供的数据比较详细。
Ubuntu下安装

sudo apt-get install bmon

然后就可以查看某一块网卡的带宽流量情况了,比如查看eth0的:

bmon -p eth0

可以看到如下显示:

Bmon查看eth0网卡情况

Bmon查看网络带宽流量情况

其中,RX表示流入,TX流出,RX rate是流入比率,TX Rate流出比率。更多bmon用法可以man bmon查看。

另外,更加喜人的是它能提供与Apache/Nginx等WEB服务器配合以Html方式动态显示流量监控结果,输入以下命令:


bmon -I distribution:multicast -o null -O html:path=/var/www/dirname/

这里注意下,上面的目录”/var/www/dirname/”最好不要用网站的根目录,因为执行下这个命令的话,它会生成一个index.html文件,而我们网站一般由一个index默认文档,一般index解析为:index.html index.htm index.php这三个文件。

所以,当它生成的index.html替换网站根目录的index.html文件的时候,访问网站时候默认就访问到bmon的统计页面了。

我们可以把他放在其他位置,然后加一个Http Auth来设定一定的权限来查看。

比如我们的网站根目录是:/var/www/website

我们把它生成的统计文件放在/var/www/website/bmon下,通过配置Nginx的Http auth_basic来控制访问权限。

在网站配置文件里加下面这么一段

location ~ ^/bmon/ {
    auth_basic Hello_Auth;
    auth_basic_user_file /data/auth/manage_auth;</pre>
}

上面的auth_basic Hello_auth;只是给这个验证加一个类似提示语的,可以任何;auth_basic_user_file 是用来存储http登录账户密码的,得用htpasswd工具来生成。具体如下:


htpasswd -c /data/passwd username

提示输入密码,就会创建一个username用户,并在/data/目录下生成username的passwd文件。

最终,通过浏览器访问http://www.xxx.com/bmon/就能看到监控的网页形式数据了。

 

 

 

Ubuntu下安装配置Subversion,并建立多个版本库

归类于Linux 参与评论

公司有好几个网站项目,随着同一个项目接手开发的同学越来越多,版本控制变成一个必须的工具。交给我来配置,在这里记录下来;

SVN可以有好几种连接方式,我这里使用的是自带的SVN://协议访问。还有通过配置apache2来使用http://访问。或者文件协议file://.

首先安装Subversion,服务器环境为Ubuntu Server.

sudo apt-get install subversion

安装成功后,就创建版本库了。

先创建一个存放版本库的文件夹,方便管理。

mkdir /var/svn

根据项目需要,创建几个不同的版本库。

cd /var/svn
svnadmin create /var/svn/aaa

执行以上命令后,可以查看aaa这个文件夹里有些什么东西:

cd aaa
ls

会看到列出:conf  db  format  hooks  locks  README.txt

进入配置文件夹conf,输命令:

cd conf
ls

可以看到列出:authz  passwd  svnserve.conf几个文件,这里说明下:

svnserve.conf:这个版本库的配置文件,包括如何验证SVN访问,访问配置文件等。命令打开编辑它:

vi svnserve.conf

看到以下代码:

[general]
# anon-access = read
# auth-access = write
...
# password-db = passwd  # 密码验证文件位置,这里去掉注释即可,为同目录下passwd文件
...
# authz-db = authz      # 同上,用户验证文件,保存可以访问用户验证信息,等下会配置
...
# realm = My first repostory

# 注释都去掉

realm = 一个类似Title说明,可以填任何字符,一般 reaml = ProjectName.

保存退出
然后编辑passwd

vi  passwd

这里配置用户信息,在[users]下输入:

[users]
username = password   # 形式如这样,用户名 = 密码,多个用户名多写几行就是

保存退出,编辑authz文件,

vi authz

下面是我添加的代码:

[groups]        # 群组
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,
aaa = root,hewei       # 用户组 = 用户名,用户名,用户名(用户名为刚才passwd里添加的用户,多个用","隔开)

[aaa:/]     # 版本库 文件夹权限配置。这里表示aaa版本库根目录下
@aaa = rw   # 对用户组赋予权限,格式:@用户组 = rw (r,读 w,写 或者为空)

到此一个版本库配置完成。

可以启动svnserv来运作。

svnserve -d -r /var/svn/       # -d表示后台运行方式启动, -r /var/svn 对svn这个目录启动

则现在可以通过以下方式连接上SVN服务器了。

比如我使用TSVN客户端,地址:svn://111.111.111.111/aaa

验证输入配置时候的用户名密码就OK了。

配置多个版本库只要再建立一个版本库:

svnadmin create -r /var/svn/bbb

然后配置同上。完了重新启动下svnserve:

killall svnserve
svnserve -d -r /var/svn/

当然,大部分时候我们可能需要配置SVN提交时候同步到WEB服务器文件目录上去,下次再把相关配置分享出来吧。

// -_-  Larro

顶部