Write once, run anywhere

Write once, run anywhere

概述

環(huán)境:LNMP(CentOS7.2 + Nginx1.10 + MariaDB10.0 + PHP5.6),Laravel5.1,Yar;

用戶(hù)Api項(xiàng)目:項(xiàng)目名:example_user_api(example可替換為具體公司的名字,代表公司的user項(xiàng)目,下同),域名:api.user.example.com,對(duì)應(yīng)數(shù)據(jù):user;

訂單Api項(xiàng)目:項(xiàng)目名:example_order_api,域名:api.order.example.com,對(duì)應(yīng)數(shù)據(jù):order;

訂單項(xiàng)目:項(xiàng)目名:example_order,域名:order.example.com;

正文

作為一名PHP后端開(kāi)發(fā)工程師,時(shí)常感受到來(lái)自項(xiàng)目deadline的壓力,而且還有需求在開(kāi)發(fā)過(guò)程中的變更。

如何應(yīng)對(duì)需求的變更和來(lái)自項(xiàng)目deadline的壓力,那就要考慮系統(tǒng)的架構(gòu)了,然后,才是編碼——為何這樣說(shuō),我喜歡用一個(gè)比喻解釋?zhuān)髲B的架構(gòu)搭建好了,壘磚就容易多了。

系統(tǒng)架構(gòu)從項(xiàng)目的角度來(lái)講有兩個(gè)方面,一方面是項(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)目之間通過(guò)RPC接口調(diào)用。

如環(huán)境描述和項(xiàng)目清單所述,環(huán)境為L(zhǎng)NMP,用戶(hù)相關(guān)項(xiàng)目有用戶(hù)Api項(xiàng)目,訂單相關(guān)項(xiàng)目有訂單Api項(xiàng)目和訂單項(xiàng)目。

讀者或許有疑問(wèn)了,這里用戶(hù)相關(guān)的只有一個(gè)項(xiàng)目,為何訂單相關(guān)的項(xiàng)目有兩個(gè),它們之間有什么區(qū)別?其實(shí),這就是Write once, run anywhere的關(guān)鍵。

用戶(hù)Api項(xiàng)目能夠?yàn)橛唵雾?xiàng)目提供Rpc服務(wù),訂單Api項(xiàng)目更是主要是為訂單項(xiàng)目提供Rpc服務(wù),這兩者本身都是沒(méi)有界面的,這也是它們?yōu)楹伪欢x為Api項(xiàng)目的原因。而訂單項(xiàng)目通過(guò)調(diào)用用戶(hù)Api項(xiàng)目和訂單Api項(xiàng)目的Rpc服務(wù),為用戶(hù)提供查看、修改等操作自己訂單的服務(wù),因此是有界面的。
然而,這也不足以要把訂單劃分成訂單Api項(xiàng)目和訂單項(xiàng)目?jī)蓚€(gè)項(xiàng)目。進(jìn)一步的原因是訂單Api項(xiàng)目不僅用于(用戶(hù)查詢(xún)、修改訂單等操作的)訂單項(xiàng)目,也可以為公司內(nèi)部的ERP系統(tǒng)提供訂單相關(guān)的Rpc服務(wù)。

代碼

Talk is easy, show me the code.
用戶(hù)Api項(xiàng)目,有t_user表,其對(duì)應(yīng)的Model為User,文件名為User.php,內(nèi)容如下:

<?php
namespace App\Model;

use DB;
use Log;
use Redis;

/**
 * 用戶(hù)表
 * @author los_gsy
 */
class User {
    /**
     * 查詢(xún)一條記錄,根據(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;
    }

}

通過(guò)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();
    }


    /**
     * 用戶(hù)
     */
    public function user(Request $req) {
        $service = new Yar_Server(new User());
        $service->handle();
    }

}

類(lèi)似的,訂單Api項(xiàng)目,有t_order表,其對(duì)應(yīng)的Model為Order,文件名為Order.php,內(nèi)容如下:

<?php
namespace App\Model;

use DB;
use Log;
use Redis;

/**
 * 訂單表
 * @author los_gsy
 */
class Order {
    /**
     * 查詢(xún)一條記錄,根據(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;
    }

}

通過(guò)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)目,在這里用戶(hù)需要查詢(xún)自己的一個(gè)訂單詳情,于是通過(guò)調(diào)用用戶(hù)Api項(xiàng)目和訂單Api項(xiàng)目的Rpc服務(wù)來(lái)實(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');

        //查詢(xún)用戶(hù)和訂單
        $user = $oUser->getById(1);
        $order = $oOrder->getById(1);

        //打印用戶(hù)和訂單信息
        var_export($user);
        var_export($order);
    }

}

結(jié)尾

Write once, run anywhere主要的思路就如上所述,以及代碼示例了。僅用于學(xué)習(xí)參考,如果是生產(chǎn)使用,還需考慮安全、性能等因素。
剛開(kāi)始在簡(jiǎn)書(shū)上寫(xiě)日志,不足之處,還請(qǐng)各位不吝賜教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容