存档

‘PHP’ 分类的存档

大型网站运营的技术经验分享

2013年3月28日 没有评论

一、日志系统

对于一个大型网站来说,代码库非常庞大,模块众多。部门协作的人数规模在百人以上,如何跟踪定位问题不像小网站那样容易。而且我们的服务器都是集群化的,动辄几千台。有一套可查询方便使用的日志系统至关重要。

对于日志的使用也有了一定的经验。我们的日志通常会非常详细的记录各种参数,环境变量,HOST等信息,在出现异常的情况下,必须要记录日志。我们使用了MySQL按时间分片的方式来记录日志,所有集群内节点均通过网络方式来写入到中心日志系统。

在管理端我们提供了很方便友好的工具,来查询定位日志,可按用户ID、类型、时间等几种索引方式查询。日志系统帮助我们定位到了很多问题。

二、PHP错误日志收集系统

PHP错误日志是所有PHP程序问题最直接的反馈渠道。通过分析PHP日志可以发现和分析出系统现有的Bug和潜在的问题。我们通过在节点部署监控工具,实时收集PHP错误日志,Fatal Error告警。解决了很多问题

三、数据统计中心

我们有一整套数据上报的系统,系统内各种接口调用、请求响应、错误返回,都会上报到数据统计中心。我们以报表的形式展现出来,可以很方便的看到每个模块,每个接口的可用性,成功率,数据规模。根据数据,我们还做了成功率告警,当接口成功率低于某个数值,比如99.99%时就会发送短信报警。还有历史数据对比报警,当发现今日数据与往期数据差距较大时,可能是系统出现了问题,会及时进行报警。

四、硬件系统报警

我们有一套工具,来监控每个服务器节点的CPU、硬盘、内存、网卡流量信息,以及其他系统关键参数的信息。并以图表方式提供展示,方便了解服务器运行情况。每次新版本,或新功能上线,都通过这些信息来感知访问量变化,以及机器的负载情况。

五、容灾工具

当一组Server中其中一台出现问题时,会及时发现,并踢掉。这个也可以做成自动容灾,不过控制不好会发生雪崩。

分类: PHP 标签:

腾讯朋友网tp_netclient.php介绍

2013年3月28日 没有评论

一、为什么要开发tp_netclient.php

大家都知道PHP有2套socket的封装:stream扩展和socket扩展。stream系列函数可以直接用fread/fwrite来读写,PHP做了一些封装,使用起来更方便。但从一下几点因素我们基于socket扩展开发了tp_netclient.php

1、超时设置的问题。调用fread读取socket时,如果没有显式设置超时那么将会取默认的socket超时值75秒。另外即使显式设置了超时,代码中如果调用了stream_socket_recvfrom,还会取默认的75秒超时(这是PHP stream_socket_recvfrom函数的bug)。一旦server端无响应,75秒的超时会使当前进程长时间阻塞。PWS,PSF,SAPS都将无法相应新的请求,造成严重的后果。tp_netclient.php默认设置了100ms,就算没接收到数据,也只会阻塞100ms,之后进程会继续处理新的请求。

2、fread有8192长度限制,一旦读到8192字节,此函数就会返回。TCP可以循环读取, UDP包就会被丢弃。这样如果用UDP协议,就不能处理超过8192字节的包。tp_netclient.php使用了socket扩展,可以支持到UDP包的最大长度65535,不存在此问题。

3、stream的socket不能设置socket option。很多有用的socket option,如SO_REUSEADDR、TCP_NODELAY都不能支持。tp_netclient.php基于socket扩展,可以很方便设置各种socket option。

4、tp_netclient.php支持waitall,在知道包长度的情况下可以一次取完,不必循环取。

5、tp_netclient.php支持UDP connect,解决了UDP串包问题

6、stream扩展是2层封装的,而socket扩展是原生socket函数的封装,性能更好。

二、tp_netclient.php如何使用

目前在朋友网系统消息模块中已广泛使用,在生产环境安全可靠无问题。

示例代码:


$client = new TP_NetClient_TCP;

if($client->connect('10.6.207.204', 19003 ,0.5))
{
   $data = 'GET /default.php HTTP/1.1\r\nHost: www.pengyou.com\r\n\r\n';
   $client->send($data);
   $cnt = $client->recv(65535);
   echo 'succ:',$cnt,'\n';
}
else
{
   echo 'faile:';
   echo $client->code;
   echo $client->msg;
}

注:此代码是私有的,大家可以直接使用swoole扩展提供的client封装。使用方法基本相同。
https://github.com/matyhtf/php_swoole/blob/master/examples/client.php

分类: PHP 标签:

PHP-AOP扩展介绍

2013年3月8日 1 条评论

项目地址:http://pecl.php.net/package/AOP

首先介绍下AOP编程,也叫做面向切面编程,是一种非倾入式编程的方法,采用外部注入的方式来取代嵌入代码。可以实现非常好的模块低耦合。

假设你的框架有一个 Frameworkd::init方法,功能是初始化框架资源。现在有db,template的初始化也需要在这个阶段执行,传统的做法就是只能修改 Frameworkd::init在里面加入 db,template的方法调用。未来如果增加了新的模块,比如cache。那就需要修改Frameworkd::init的代码。这种做法显然是侵入性的。

当然也可以用hook list的方式来实现。在需要外部注入的地方加入一个hook list,遍历执行外部注入的接口。但远没有AOP强大,而且还需要不断加入hook list的遍历点。

如果AOP编程的话,只需要外部注入一个函数,执行 Frameworkd::init时,就会执行指定的代码。


<?php
class MyServices
{
        public function doAdminStuff1 ()
        {
                //some stuff only the admin should do
                echo "Calling doAdminStuff1\n";
        }

        public function doAdminStuff2 ()
        {
                //some stuff only the admin should do
                echo "Calling doAdminStuff2\n";
        }
}

function adviceForDoAdmin ()
{
        echo "AOP[1] Run\n";
}

function adviceForDoAdmin2 ()
{
        echo "AOP[2] Run\n";
}
aop_add_after('MyServices->doAdmin*()', 'adviceForDoAdmin');
aop_add_after('MyServices->doAdmin*()', 'adviceForDoAdmin2');
$o = new MyServices;
$o->doAdminStuff1();
$o->doAdminStuff2();

执行结果:

Calling doAdminStuff1
AOP[2] Run
AOP[1] Run
Calling doAdminStuff2
AOP[2] Run
AOP[1] Run
分类: PHP 标签:

腾讯PSF框架介绍

2013年1月28日 没有评论

PSF是腾讯开发的一套完全使用PHP开发的逻辑Server框架,基于epoll异步事件通知模型。支持TCP长连接、TCP短连接、UDP,3种模式。TCP使用了经典的Multi-Reactor模型,UDP使用类似LVS的半同步/半异步模型,运行效率很高。在高并发高负载的环境可快速稳定地运行。

PSF拥有完善的多配置多插件管理体系,健壮的Worker进程管理系统,全自动柔性重启策略。PSF框架支撑着很多逻辑层Server,有数百台线上服务器运行着PSF的插件。在公司内的四层架构建设中发挥了很大的作用。

PSF使用简单方便,开发人员无需关注底层实现,只需专注于业务逻辑开发。PSF采用了单一配置文件,开发人员只需要修改配置文件即可调整监听IP、端口、资源分配、协议类型、业务组件的上线/下线以及服务器扩容。配置文件中提供了很多选项,可以针对业务的特征,对Server的运行参数进行微调。

PSF框架性能非常好,并发2000压测,一个简单的EchoServer,TCP每秒可处理4万个请求,UDP可处理6万请求。

分类: PHP 标签:

PHP的Session数据同步问题

2013年1月23日 没有评论

近来公司某个域名流量大涨,发现一个外部QQ登录的接口经常失败,用户登录总是不成功。经过排查发现是登录的第一步需要保存一个token_secret。当时的程序员编写此代码时直接用了$_SESSION来保存token_secret。这里在并发量小时问题不大,并发大了之后极有可能会出问题。

假设A,B两个请求同时出发,A,B同时session_start,读取到了一个$_SESSION的值。当A完成请求写入$_SESSION,但B还没有完成请求,B完成请求后再写$_SESSION,就会覆盖A所设置的值。

类似的数据同步问题其实很多的,比如file_put_contents写PHP的Cache文件,如果不加LOCK_EX就可能会存在同步问题,当一个进程写file时,只写到一半有另外的进程去require此文件,这时就会因为文件不完整,导致PHP语法错误。所以涉及到同时读写同一个文件或数据时一定要加锁,否则在高并发的情况下会产生严重错误。

分类: PHP 标签:

PHP如何为函数执行设置超时

2013年1月14日 没有评论

如何防止一个函数执行时间过长呢?在PHP里可以用pcntl时钟信号+异常来实现。

代码如下:


<?php
declare(ticks = 1);
function a()
{
    sleep(10);
    echo "a finishi\n";
}
function b()
{
    echo "Stop\n";
}
function c()
{
    usleep(100000);
}

function sig()
{
    throw new Exception;
}

try
{
    pcntl_alarm(1);
    pcntl_signal(SIGALRM, "sig");
    a();
    pcntl_alarm(0);
}
catch(Exception $e)
{
    echo "timeout\n";
}

b();
a();
b();

原理是在函数执行前先设定一个时钟信号,如果函数的执行超过规定时间,信号会被触发,信号处理函数会抛出一个异常,被外层代码捕获。这样就跳出了原来函数的执行,接着执行下面的代码。如果函数在规定的时间内,时钟信号不会触发,在函数结束后清除时钟信号,不会有异常抛出。

分类: PHP 标签:

Go语言特性介绍

2013年1月11日 没有评论

Go语言是google推出的一个静态编译型语言,目标是取代C、C++、Java作为系统开发的语言。开发者很多都是来自贝尔实验室的大神。Go语言包含了很多非常酷的语言特性,值得尝试。

目前Google、盛大、金山、百度等公司已经开始使用Go语言开发系统模块了。本文重点介绍下Go语言区别于一般语言的特性。其他语言,比如内置数据结构,内存管理,闭包,反射等共有的特性就不说了,Go语言全部都有。
1、语言级别的原生并发机制:goroutine
C/C++、java C#等语言都有并发的库,一般都是对操作系统的线程或进程库做封装,使用很不方便。
比如Pthread线程。
Go语言内建了并发机制,使用非常简单。Go语言会自己调度goroutine。goroutine的实现也很高效,可以同时开启几十万个goroutine,而且goroutine之间互相切换成本很低。
  1. func abc(s sting){
  2.      time.Sleep(1);
  3.      fmt.Println(s);
  4. }
  5. //普通的串行调用
  6. abc(“hello”)
  7. //Go语言并行调用
  8. go abc(“hello”)

Go语言还提供了远程RPC调用,执行go func() 时甚至可以是分布式调用的。

2、语言级别的管道通信机制:channel
大部分语言都是用共享内存方式进行通信,而Go语言完全使用消息传递来进行通信,安全高效无锁。
channel可以干各种事情,用来做消息传递,管道,缓冲区,mutex等等,还可以配合使用select语法。
  1. ch := make(chan int, 1000)
  2. go func(){
  3.     time.Sleep(1e9)
  4.     ch <- 999  //写入数据
  5. }
  6. num = <- ch //读数据

chan还可以当成参数传递。Go语言还提供了netchan,可以跨越网络实现消息传递。

3、语言级别的延迟执行特性:defer
比如连接mysql,调用完成后,需要关闭连接一般语言要很小心地考虑加在什么地方。如何处理好异常,比如Java中复杂的final语法。Go语言可以非常轻松的实现,只需要在开始的时候加defer,具体什么时间调用,Go语言会帮你处理。
  1. db.Connect(host, port, db)
  2. defer db.Close()
  3. …//读取数据库

4、语言级别的多返回值特性

C/C++、Java、PHP之类语言想要return多个值,需要很复杂的处理。Go语言很简单,语言天然支持。
  1. ret1, ret2 = func1()
  2. func func1()(ret1 int, ret2 int){
  3.    ret1 := 1
  4.    ret2 := 2
  5.    return ret1, ret2
  6. }

5、Go语言不用写 ;结束符

6、Go语言通过首字母大小写来控制public、private

7、Go语言可以跟C语言无缝结合
分类: PHP 标签:

写好PHP的6个建议

2013年1月11日 没有评论

写好PHP代码真的不容易,给大家几个建议:

  1. 慎用全局变量,全局变量不好管理的,会导致你的代码依赖于全局变量,而耦合度太高。
  2. 一定不要复制粘贴代码,可重用的代码一定要写成函数,或者类。等你代码多了,就知道这个多么重要了。
  3. 不要硬编码数据到代码中,一定要可配置化。如果是全局使用的就搞个全局config。如果仅在类中使用,请使用类静态变量配置。别直接在代码里头写
  4. 程序的结构化要做好,先规划一个流程。代码怎么运转的,要很清晰,有主线,从A->B->C,一眼就明白了,而且很容易修改流程和增加,替换环节。不要A直接进入B然后没踪影了,然后在B中又进入C又没踪影了。
  5. 搞个Trace系统,在你的代码中加入Trace来进行调试。跟踪变量的变化,这样会很方便。发布代码时,可注释掉所有Trace,只需要批量替换即可。
  6. 多写点单元测试的脚本,一旦更改了代码,做了大的版本更新。不需要你挨个去试,跑一下单元测试就知道是不是有的地方出问题了。
分类: PHP 标签:

说说产品驱动型的管理模式

2013年1月6日 1 条评论

很多IT公司都采用产品驱动技术的管理模式,我们腾讯也是如此。身为一个程序员不得不对这种模式做点评价。

不可否认这种模式会比较快得作出产品来,虽然开发出的产品不一定会是最好,最起码不会是最差。另外产品开发的成功率也得到了保证,不至于做了一半不搞了。

但是也顺便讲讲他的坏处吧。产品驱动的开发模式最致命的问题是:会让所有程序员彻底失去积极性。无论多么棒的Idea,多么有意思的Idea,只要用了这种模式,程序员的那种积极性,创新性都将不存在了。逐渐会产生另外一个问题,反正不是我主导的,我不用再思考了,你们怎么说我就怎么做吧。效率越来越差劲。如果军队是参谋指挥将军,打起仗来会怎么样?

谈论下Facebook的管理模式吧。他们也有产品经理,但主要产品的是技术人员而不是产品经理,产品经理负责给技术出谋划策,提供信息帮助技术人员。他们的效率很高。

腾讯也是产品驱动型的管理模式,不过广州研发部是个例外,也正是因为例外,所以他们搞出了QQ邮箱,微信这样的重量级产品来。

分类: PHP 标签:

大型网站运营的技术经验分享

2013年1月6日 没有评论

一、日志系统

对于一个大型网站来说,代码库非常庞大,模块众多。部门协作的人数规模在百人以上,如何跟踪定位问题不像小网站那样容易。而且我们的服务器都是集群化的,动辄几千台。有一套可查询方便使用的日志系统至关重要。

对于日志的使用也有了一定的经验。我们的日志通常会非常详细的记录各种参数,环境变量,HOST等信息,在出现异常的情况下,必须要记录日志。我们使用了MySQL按时间分片的方式来记录日志,所有集群内节点均通过网络方式来写入到中心日志系统。

在管理端我们提供了很方便友好的工具,来查询定位日志,可按用户ID、类型、时间等几种索引方式查询。日志系统帮助我们定位到了很多问题。

二、PHP错误日志收集系统

PHP错误日志是所有PHP程序问题最直接的反馈渠道。通过分析PHP日志可以发现和分析出系统现有的Bug和潜在的问题。我们通过在节点部署监控工具,实时收集PHP错误日志,Fatal Error告警。解决了很多问题

三、数据统计中心

我们有一整套数据上报的系统,系统内各种接口调用、请求响应、错误返回,都会上报到数据统计中心。我们以报表的形式展现出来,可以很方便的看到每个模块,每个接口的可用性,成功率,数据规模。根据数据,我们还做了成功率告警,当接口成功率低于某个数值,比如99.99%时就会发送短信报警。还有历史数据对比报警,当发现今日数据与往期数据差距较大时,可能是系统出现了问题,会及时进行报警。

四、硬件系统报警

我们有一套工具,来监控每个服务器节点的CPU、硬盘、内存、网卡流量信息,以及其他系统关键参数的信息。并以图表方式提供展示,方便了解服务器运行情况。每次新版本,或新功能上线,都通过这些信息来感知访问量变化,以及机器的负载情况。

五、容灾工具

当一组Server中其中一台出现问题时,会及时发现,并踢掉。

 

分类: PHP 标签: