运营后台的自动化与规范化

规范化
   为何谈这个呢?就在昨天我们的运营人员将一个活动的测试地址发到线上。通过长连接服务下
发的。等到发现的时候已经距事发3个多小时了。影响至少2000w用户,很不好的一次体验了。
    立即响应: 1. 让消息失效
             2. 临时将测试地址访问切到线上 汗...(唯一的解决方案)

   这种事责任在谁呢? 运营人员?不,他们只是配置内容。可能内容也没关注过。 这责任就在
没有相关的规范化。一定的规范化在很大程度上可以减少此类事情发生(很多运营后台都存在这样的
问题)。怎么预防和解决呢?
    层层把关! 从产品到运营,运营到后台,后台到技术。一般情况下,像页面等测试环境与线上
环境完全一致。运营人员可能没关注到地址细节。这种测试可能疏漏掉。那最后一道关卡就落到技术
人员身上了。对上线的配置(特别是包含链接的)最好过滤提示运营人员。
自动化
   自动化而言,就是将运营人员干的事,提炼,总结。发现规律并使用程序实现,让程序来完成人
该干的事。从而节省人力,节省时间,快速响应。
   最近产品老为了收入,做一些专题活动,要求优先展示广告。前后提供了四五次接口,发现总有
很多小的变动,大体又变化不大。看看代码重复的比较多。真是心碎了。 另外就是上线一次专题活动
至少得两天(运营准备素材,我导入数据并提供接口,再等页面开发(代码估计乱了),最后在测试上线)

    就提建议给产品,将这个流程自动化。自动化包括后台模板开发,接口对接后台开发接口,
前端开发页面动态渲染。整个工作也就三天多。现在上线的所需时间直接等于运营配置后台的时间。

    自动化的难点: 发现规律,制定规则

open-falcon监控lnmp应用

目标
业务部门监控线上lnmp,快速定位问题,从而快速响应
对于开发者,各个组件的主要衡量指标:
    linux: 集群存活状态,机器负载,网卡流量  ----- 对外服务的server状态
    nginx: 接口状态                        ----- 用户访问情况
    mysql: db的可用性                   ----- 类似依赖资源的可用性
    php  : faltal,warning               ----- 代码问题
实践
监控数据展示的三个层次:
    1. 项目整体
    2. 项目对应机房情况
    3. 项目依赖资源状态

一.整体概况:

all

二.单个机房情况(除了有与项目整体相同的,还有下图接口数据)

all

三. 项目依赖资源的可用性监控数据(需要在server自己探测资源可用情况)

参考:
部署: http://book.open-falcon.org/zh/intro/index.html
github: https://github.com/open-falcon

《奇特的一生》摘录

我们真诚地相信我们是尽力而为,认真地埋头工作,蓦然发现我们真正做工作的时间说不定只有
一个小时,一个半小时,其余的时间都流走了,消逝了,浪费在无谓的奔忙和聊天上,浪费在等待
鸿鹄将至。我们不是挺珍惜每一分钟的嘛,放弃了休息,摒绝了娱乐……

接口开发中共享资源的Cache处理

这里共享资源的定义,就是多个用户可能同时访问到的资源。比如功能首页的列表,活动页面等等。
方案1:后台脚本刷新
通过后台脚本将后台配置的内容定时刷新到cache中,接口直接读对应键内容。

特点:1. server主动更新Cache
     2. 所有用户读到的内容都是一致的。
     3. 如果后台没有设置有效期。前端接口可以100%读到数据

适用场景: 对对象信息的处理,如商品信息,应用信息等。供其他服务适用
方案2:定时失效更新
一个用户读数据,缓存不存在时,访问db然后cache(固定有效期),最后返回给用户。之后在这段
有效期内所有用户访问该数据会直接返回cache内容。等cache失效会重新读库并cache

特点: 1. Cache随用户访问更新
      2. 可能引发cache穿透。大量访问压向后台db,频繁更新无用的Cache
      3. 为了处理穿透,部分用户访问的内容可能不同

适用场景: 列表资源,涉及分页等处理。
如何处理穿透?
1. cache失效时,多个用户访问只许一个访问db(加锁)。别的用户访问到锁则不进行数据库访问
2. cache失效,那些访问到锁又不查库。给用户返回空数据? 不行! 怎么处理? 假失效!
    如何假失效? key 对应的数据 =》 (DB内容 + expire过期截止时间) 。 expire大于当前
    时间说明失效,去访问DB,发现有锁,说明别人已经在更新缓存。自己则返回本该失效的内容。

php常用设计模式整理

策略模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
/**
* 策略模式
* 定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化
*
*/
/**
* 出行旅游
*
*
*/
interface TravelStrategy{
public function travelAlgorithm();
}
/**
* 具体策略类(ConcreteStrategy)1:乘坐飞机
*/
class AirPlanelStrategy implements TravelStrategy {
public function travelAlgorithm(){
echo "travel by AirPlain", "<BR>\r\n";
}
}
/**
* 具体策略类(ConcreteStrategy)2:乘坐火车
*/
class TrainStrategy implements TravelStrategy {
public function travelAlgorithm(){
echo "travel by Train", "<BR>\r\n";
}
}
/**
* 具体策略类(ConcreteStrategy)3:骑自行车
*/
class BicycleStrategy implements TravelStrategy {
public function travelAlgorithm(){
echo "travel by Bicycle", "<BR>\r\n";
}
}
/**
*
* 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
* 算法解决类,以提供客户选择使用何种解决方案:
*/
class PersonContext{
private $_strategy = null;
public function __construct(TravelStrategy $travel){
$this->_strategy = $travel;
}
/**
* 旅行
*/
public function setTravelStrategy(TravelStrategy $travel){
$this->_strategy = $travel;
}
/**
* 旅行
*/
public function travel(){
return $this->_strategy ->travelAlgorithm();
}
}
// 乘坐火车旅行
$person = new PersonContext(new TrainStrategy());
$person->travel();
// 改骑自行车
$person->setTravelStrategy(new BicycleStrategy());
$person->travel();
?>
观察者模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
/**
*参考IBM官网:http://www.ibm.com/developerworks/cn/opensource/os-php-designptrns/
*@author http://www.phpddt.com
*/
//观察者
interface IObserver
{
public function notify();
}
//定义可以被观察的对象接口
interface IObservable
{
public function addObserver($observer);
}
//实现IObservable接口
class MessageSystem Implements IObservable
{
private $_observers = array();
public function addObserver($observer)
{
$this->_observers = $observer;
}
public function doNotify()
{
foreach($this->_observers as $o)
{
$o->notify();
}
}
}
//实现IObserver接口
class User Implements IObserver
{
public function __construct($username)
{
echo "我是新用户{$username}<br/>";
}
//通知观察者方法
public function notify()
{
echo '欢迎新用户';
}
}
//使用
$u = new MessageSystem();
$u->addObserver(new User('小明'));
//$u->addObserver(new User('小红'));
//$u->addObserver(new User('小黑'));
$u->doNotify();
单例模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
{
protected static $_instance = null;
protected function __construct()
{
//disallow new instance
}
protected function __clone(){
//disallow clone
}
public function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new self();
}
return self::$_instance;
}
}
工厂模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class DbFactory
{
function static factory($db_class_name)
{
$db_class_name = strtolower($db_class_name);
if (include_once 'Drivers/' . $db_class_name . '.php') {
$classname = 'Driver_' . $db_class_name;
return new $db_class_name;
} else {
throw new Exception ('对应的数据库类没找到');
}
}
}
适配器模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
//目标角色
interface Target {
public function simpleMethod1();
public function simpleMethod2();
}
//源角色
class Adaptee {
public function simpleMethod1(){
echo 'Adapter simpleMethod1';
}
}
//类适配器角色
class Adapter implements Target {
private $adaptee;
function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
//委派调用Adaptee的sampleMethod1方法
public function simpleMethod1(){
echo $this->adaptee->simpleMethod1();
}
public function simpleMethod2(){
echo 'Adapter simpleMethod2';
}
}
//客户端
class Client {
public static function main() {
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
$adapter->simpleMethod1();
$adapter->simpleMethod2();
}
}
Client::main();
?>
装饰器模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//被装饰者基类
interface Component
{
public function operation();
}
//装饰者基类
abstract class Decorator implements Component
{
protected $component;
public function __construct(Component $component)
{
$this->component = $component;
}
public function operation()
{
$this->component->operation();
}
}
//具体装饰者类
class ConcreteComponent implements Component
{
public function operation()
{
echo 'do operation'.PHP_EOL;
}
}
//具体装饰类A
class ConcreteDecoratorA extends Decorator {
public function __construct(Component $component) {
parent::__construct($component);
}
public function operation() {
parent::operation();
$this->addedOperationA(); // 新增加的操作
}
public function addedOperationA() {
echo 'Add Operation A '.PHP_EOL;
}
}
//具体装饰类B
class ConcreteDecoratorB extends Decorator {
public function __construct(Component $component) {
parent::__construct($component);
}
public function operation() {
parent::operation();
$this->addedOperationB();
}
public function addedOperationB() {
echo 'Add Operation B '.PHP_EOL;
}
}
class Client {
public static function main() {
/*
do operation
Add Operation A
*/
$decoratorA = new ConcreteDecoratorA(new ConcreteComponent());
$decoratorA->operation();
/*
do operation
Add Operation A
Add Operation B
*/
$decoratorB = new ConcreteDecoratorB($decoratorA);
$decoratorB->operation();
}
}
Client::main();
转自: http://www.phpddt.com/php/design-decoration.html