Write once, run anywhere
概述
環(huán)境:LNMP(CentOS7.2 + Nginx1.10 + MariaDB10.0 + PHP5.6),Laravel5.1堤撵,Yar;
用戶Api項(xiàng)目:項(xiàng)目名:example_user_api(example可替換為具體公司的名字伏伐,代表公司的user項(xiàng)目裂七,下同),域名:api.user.example.com哄陶,對應(yīng)數(shù)據(jù):user才避;
訂單Api項(xiàng)目:項(xiàng)目名:example_order_api橱夭,域名:api.order.example.com,對應(yīng)數(shù)據(jù):order桑逝;
訂單項(xiàng)目:項(xiàng)目名:example_order棘劣,域名:order.example.com;
正文
作為一名PHP后端開發(fā)工程師楞遏,時常感受到來自項(xiàng)目deadline的壓力茬暇,而且還有需求在開發(fā)過程中的變更。
如何應(yīng)對需求的變更和來自項(xiàng)目deadline的壓力寡喝,那就要考慮系統(tǒng)的架構(gòu)了糙俗,然后,才是編碼——為何這樣說预鬓,我喜歡用一個比喻解釋巧骚,大廈的架構(gòu)搭建好了,壘磚就容易多了。
系統(tǒng)架構(gòu)從項(xiàng)目的角度來講有兩個方面劈彪,一方面是項(xiàng)目與項(xiàng)目之間的搭配竣蹦,另一方面是項(xiàng)目本身的分層。
本文主要講項(xiàng)目與項(xiàng)目之間的搭配這一方面的架構(gòu)粉臊,也就是實(shí)現(xiàn)Write once, run anywhere的基礎(chǔ)草添。先下結(jié)論:項(xiàng)目與項(xiàng)目之間通過RPC接口調(diào)用。
如環(huán)境描述和項(xiàng)目清單所述扼仲,環(huán)境為LNMP,用戶相關(guān)項(xiàng)目有用戶Api項(xiàng)目抄淑,訂單相關(guān)項(xiàng)目有訂單Api項(xiàng)目和訂單項(xiàng)目屠凶。
讀者或許有疑問了,這里用戶相關(guān)的只有一個項(xiàng)目肆资,為何訂單相關(guān)的項(xiàng)目有兩個矗愧,它們之間有什么區(qū)別?其實(shí)郑原,這就是Write once, run anywhere的關(guān)鍵唉韭。
用戶Api項(xiàng)目能夠?yàn)橛唵雾?xiàng)目提供Rpc服務(wù),訂單Api項(xiàng)目更是主要是為訂單項(xiàng)目提供Rpc服務(wù)犯犁,這兩者本身都是沒有界面的属愤,這也是它們?yōu)楹伪欢x為Api項(xiàng)目的原因。而訂單項(xiàng)目通過調(diào)用用戶Api項(xiàng)目和訂單Api項(xiàng)目的Rpc服務(wù)酸役,為用戶提供查看住诸、修改等操作自己訂單的服務(wù),因此是有界面的涣澡。
然而贱呐,這也不足以要把訂單劃分成訂單Api項(xiàng)目和訂單項(xiàng)目兩個項(xiàng)目。進(jìn)一步的原因是訂單Api項(xiàng)目不僅用于(用戶查詢入桂、修改訂單等操作的)訂單項(xiàng)目奄薇,也可以為公司內(nèi)部的ERP系統(tǒng)提供訂單相關(guān)的Rpc服務(wù)。
代碼
Talk is easy, show me the code.
用戶Api項(xiàng)目抗愁,有t_user表馁蒂,其對應(yīng)的Model為User,文件名為User.php驹愚,內(nèi)容如下:
<?php
namespace App\Model;
use DB;
use Log;
use Redis;
/**
* 用戶表
* @author los_gsy
*/
class User {
/**
* 查詢一條記錄远搪,根據(jù)id
* @param int $id
* @return null | object
*/
static public function getById($id) {
$result = DB::connection('user')->table('user')
->where('id', $id)
->first();
if (!$result) {
Log::warning(__METHOD__ . ': $param = ' . var_export(func_get_args(), true));
}
return $result;
}
}
通過Controller封裝成Rpc服務(wù),這里取文件名為ModelController.php逢捺,內(nèi)容如下:
<?php
namespace App\Http\Controllers\Rpc;
use App\Http\Controllers\Controller;
use App\Model\User;
use Illuminate\Http\Request;
use Log;
use Yar_Server;
/**
* 模型
* @author los_gsy
*/
class ModelController extends Controller {
/**
* 構(gòu)造函數(shù)
*/
public function __construct(Request $req) {
parent::__construct();
}
/**
* 用戶
*/
public function user(Request $req) {
$service = new Yar_Server(new User());
$service->handle();
}
}
類似的谁鳍,訂單Api項(xiàng)目,有t_order表,其對應(yīng)的Model為Order倘潜,文件名為Order.php绷柒,內(nèi)容如下:
<?php
namespace App\Model;
use DB;
use Log;
use Redis;
/**
* 訂單表
* @author los_gsy
*/
class Order {
/**
* 查詢一條記錄,根據(jù)id
* @param int $id
* @return null | object
*/
static public function getById($id) {
$result = DB::connection('order')->table('order')
->where('id', $id)
->first();
if (!$result) {
Log::warning(__METHOD__ . ': $param = ' . var_export(func_get_args(), true));
}
return $result;
}
}
通過Controller封裝成Rpc服務(wù)涮因,這里同樣取文件名為ModelController.php废睦,內(nèi)容如下:
<?php
namespace App\Http\Controllers\Rpc;
use App\Http\Controllers\Controller;
use App\Model\Order;
use Illuminate\Http\Request;
use Log;
use Yar_Server;
/**
* 模型
* @author los_gsy
*/
class ModelController extends Controller {
/**
* 構(gòu)造函數(shù)
*/
public function __construct(Request $req) {
parent::__construct();
}
/**
* 訂單
*/
public function order(Request $req) {
$service = new Yar_Server(new Order());
$service->handle();
}
}
訂單項(xiàng)目,在這里用戶需要查詢自己的一個訂單詳情养泡,于是通過調(diào)用用戶Api項(xiàng)目和訂單Api項(xiàng)目的Rpc服務(wù)來實(shí)現(xiàn)嗜湃,代碼如下:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Yar_Client;
/**
* 訂單
* @author los_gsy
*/
class OrderController extends Controller {
/**
* 構(gòu)造函數(shù)
*/
public function __construct(Request $req) {
parent::__construct();
}
/**
* tmp
* @param Request $req
*/
public function tmp(Request $req) {
//定義變量
$oUser = new Yar_Client('http://api.user.example.com/Rpc/Model/user');
$oOrder = new Yar_Client('http://api.order.example.com/Rpc/Model/order');
//查詢用戶和訂單
$user = $oUser->getById(1);
$order = $oOrder->getById(1);
//打印用戶和訂單信息
var_export($user);
var_export($order);
}
}
結(jié)尾
Write once, run anywhere主要的思路就如上所述,以及代碼示例了澜掩。僅用于學(xué)習(xí)參考购披,如果是生產(chǎn)使用,還需考慮安全肩榕、性能等因素刚陡。
剛開始在簡書上寫日志,不足之處株汉,還請各位不吝賜教筐乳。