1、框架内开发
传统php代码向swoole框架升级
直接使用如: think-swoole、swooletw/laravel-swoole ,面向对象编程的好处体现、很方便,QPS相对对简单页面有15+倍的提升。但《(网络学习)3、秒杀系统与压力测试》实测发现,只有2~3倍的提升,甚至更低。而原生hyperf框架测试确实很好看,此时性能差在哪里?数据库、apcu缓存。
a.传统php代码向swoole框架升级
改造步骤:
php编译配置添加cli、swoole支持;swoole配置、兼容情况参考官网。
创建swoole-http对象,启动监听事件
$http = new Swoole\Http\Server("127.0.0.1", 9501);
$http->on("request", function ($request, $response) {
//ROUTE操作
$response->header("Content-Type", "text/plain");
$response->end("Hello World\\n");
});
$http->start();
添加一键协程化配置
SwooleRuntime::enableCoroutine($flags = SWOOLE_HOOK_ALL);
apcu开启: apc.enable_cli
进程隔离: 如果需要在不同的 Worker 进程内共享数据,可以用Redis
、MySQL
、文件
、Swoole\Table
、APCu
、shmget
等工具实现
php --ri apcu
apc.enable_cli => Disabled 默认值 > 1
[APCU运行时配置] https://www.php.net/manual/zh... 压测提升情况。
swoole-table
$table = new Swoole\Table(1024);
$table->column('total_count', Swoole\Table::TYPE_INT);
$table->column('local_count', Swoole\Table::TYPE_INT);
$table->column('use_num', Swoole\Table::TYPE_INT);
$table->column('server_num', Swoole\Table::TYPE_INT);
$table->create();
$GLOBALS['table'] = &$table;
($GLOBALS['table'])->set(self::$REDIS_REMOTE_HT_KEY, [
'redis_key' => self::$REDIS_REMOTE_HT_KEY,
'total_count' => $num,
'local_count' => $stock,
'use_num' => 0,
'server_num' => $data['server_num'],
]);
$data = ($GLOBALS['table'])->get(self::$REDIS_REMOTE_HT_KEY);
使用swoole框架,逐类重构
重构项目另设监听端口,与原项目并行使用、nginx分配权重。
b.接口开发:restful风格接口
阮一峰:《RESTful API 设计指南》
版本控制
https://api.example.com/v1/
体现资源
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
HTTP动词
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
过滤信息
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
错误处理、返回结果
{
error: "Invalid API key"
}
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
推荐使用:OAuth 2.0、JSON通讯
OAuth 2.0:
客户端 ---- [ 鉴权端 -- 资源端 ]
Hypermedia API一种复杂风格约束
我们从假定这些服务只公布 __一个__ 对外发布的URI。
Richardson 提出的 REST 成熟度模型。该模型把 REST 服务按照成熟度划分成 4 个层次:
- 第一个层次(Level 0)的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。* 第二个层次(Level 1)的 Web 服务引入了资源的概念。每个资源有对应的标识符和表达。
- 第三个层次(Level 2)的 Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用 HTTP 状态码来表示不同的结果。如 HTTP GET 方法来获取资源,HTTP DELETE 方法来删除资源。
- 第四个层次(Level 3)的 Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。
c.接口开发:RPC远程过程调用
客户端 ---- [ 服务端rpc.client -- 计算端rpc.server >> consul服务排队管理 ]
2、设计模式
菜鸟教程 > 设计模式及示例(Java)
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
a.创建型模式
旨在将系统与它的对象创建、结合、表示的方式分离,增强对象和类之间的独立性
1) [工厂模式] 使用通用的接口类:封装类中变化的方法,实现放到子类实现;
2) [抽象工厂模式] 组合`工厂`接口类,手动选择工厂类;
3) [单例模式] 防止拷贝:对象引用赋值时,禁用拷贝:覆盖__clone、另写getInstance方法;
4) [建造者模式**]:建造者模式(Builder Pattern)
5) [原型模式] 浅拷贝|写复制对象;
建造者模式(Builder Pattern)
实例
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
1、定义复杂[多级组合]
父级产品类、构造类: all-in-one[1-Product产品
&ProductBuilder产品构建器
],接口ProductInterface、Hardware、Software,
name = $name; }
/**
* 构建硬件
*
* @param Hardware $hardware 硬件参数
* @return void
*/
public function addHardware(Hardware $instance)
{
$this->hardwares[] = $instance;
}
/**
* 构建软件
*
* @param Software $software 软件参数
* @return void
*/
public function addSoftware(Software $instance)
{
$this->softwares[] = $instance;
}
}
'',
'hardware' => [],
'software' => []
];
/**
* 构造函数
*/
public function __construct($params = []) { }
/**
* mp3
*
* @param array $params 参数
* @return Product Mp3
*/
public function getMp3($params = [])
{
$this->params = $params;
$mp3 = new Product($this->params['name']);
$mp3->addHardware(new HardwareCpu($this->params['hardware']['cpu']));
$mp3->addHardware(new HardwareRam($this->params['hardware']['ram']));
$mp3->addHardware(new HardwareStorage($this->params['hardware']['storage']));
$mp3->addSoftware(new SoftwareOs($this->params['software']['os']));
return $mp3;
}
/**
* phone
*
* @param array $params 参数
* @return Product Phone
*/
public function getPhone($params = [])
{
$this->params = $params;
$phone = new Product($this->params['name']);
$phone->addHardware(new HardwareScreen($this->params['hardware']['screen']));
$phone->addHardware(new HardwareCamera($this->params['hardware']['camera']));
$phone->addHardware(new HardwareCpu($this->params['hardware']['cpu']));
$phone->addHardware(new HardwareRam($this->params['hardware']['ram']));
$phone->addHardware(new HardwareStorage($this->params['hardware']['storage']));
$phone->addSoftware(new SoftwareOs($this->params['software']['os']));
return $phone;
}
}
2、定义产品概念类[2-Mp3
、Phone
]、实现父级概念接口[ProductInterface],
_name = $name;
$this->hardware($hardware);
$this->software($software);
}
/**
* 构建硬件
*
* @param array $hardware 硬件参数
* @return void
*/
public function hardware($hardware=array())
{
$this->_cpu = new HardwareCpu($hardware['cpu']); // 创建 CPU
$this->_ram = new HardwareRam($hardware['ram']); // 创建内存
$this->_storage = new HardwareStorage($hardware['storage']); // 创建存储
}
/**
* 构建软件
*
* @param array $software 软件参数
* @return void
*/
public function software($software=array())
{
$softwareOs = new SoftwareOs(); // 创建操作系统
$this->_os = $softwareOs->produce($software['os']);
}
}
3、定义组件类[3-HardwareCpu、SoftwareOs...
],
_quantity = $quantity; }
}
_os = $os; }
}
构建实例
名称,硬件, 软件
* // 硬件又由以下硬件构成
* 硬件 => 屏幕,cpu, 内存, 储存, 摄像头
* // 软件又由以下构成
* 软件 => android, ubuntu
*
* * // mp3简单由以下构成
* 手机 => 名称,硬件, 软件
* // 硬件又由以下硬件构成
* 硬件 => cpu, 内存, 储存
* // 软件又由以下构成
* 软件 => mp3 os
*/
// 注册自加载
spl_autoload_register('autoload');
function autoload($class)
{
require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php';
}
/************************************* test *************************************/
use builder\ProductBuilder;
$builder = new ProductBuilder();
// 生产一款mp3
$builder->getMp3([
'name' => '某族MP3',
'hardware' => [
'cpu' => 1,
'ram' => 1,
'storage' => 128,
],
'software' => ['os' => 'mp3 os']
]);
echo "\n";
echo "----------------\n";
echo "\n";
// 生产一款手机
$builder->getPhone([
'name' => '某米8s',
'hardware' => [
'screen' => '5.8',
'camera' => '2600w',
'cpu' => 4,
'ram' => 8,
'storage' => 128,
],
'software' => ['os' => 'android 6.0']
]);
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
b.结构型模式
借由一以贯之的方式来了解元件间的关系,以简化设计:连接|接口选择
6) [适配器模式] 处理类,替换原类调用,逻辑选择接口、继续处理;
7) [桥接模式**] 接口类,把多角度分类分离出来,让它们独立变化,减少它们之间耦合;
8) [过滤器模式] 处理类,批量遍历、逻辑解耦;
9) [组合模式]:处理类,组合模式(Composite Pattern)可以对象添加到另一个的内含列表,用于层次结构管理:如树形打印;
10) [装饰器模式**] 处理类,包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能;
11) [外观模式] (Facade Pattern)处理类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用;
桥接模式(Bridge Pattern)
实例
步骤 1 创建桥接实现接口,实现类
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}
//创建实现了 DrawAPI 接口的实体桥接实现类。
RedCircle.java
public class DrawRedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: "
+ radius +", x: " +x+", "+ y +"]");
}
}
GreenCircle.java
public class DrawGreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: "
+ radius +", x: " +x+", "+ y +"]");
}
}
步骤 2 创建抽象类 Shape,使用 DrawAPI 接口
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}
//创建实现了 Shape 接口的实体类。
Circle.java
public class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI); //parent(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(radius,x,y);
}
}
步骤 3 使用 Shape 和 DrawAPI 类画出不同颜色的圆。
BridgePatternDemo.java
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100,100, 10, new RedCircle());
Shape greenCircle = new Circle(100,100, 10, new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}
装饰器模式(Decorator Pattern)
装饰器类
创建实现了 Shape 接口的抽象装饰类。
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
//do1
decoratedShape.draw();
//do2
}
}