ساختار میکروسرویس های دانشگاه فردوسی مشهد

تاريخ آخرين ويرايش: 21 خرداد 1399

اداره سامانه هاي كاربردي مركز فاوا دانشگاه فردوسي مشهد

جهت پیاده سازی میکروسرویس ها در سیستم های دانشگاه فردوسی مشهد میکروفریم ورک Slim از میان میکروفریم ورک های موجود انتخاب شده است. برای کار با Slim لازم است تا حدی کار با composer را بیاموزیم.

ساختار

معماري ميكروسرويس به اختصار به صورت زیر می باشد:
sakhtar

همانطور که در شکل قابل مشاهده است کلاینت های میکروسرویس پورتالهای مختلف دانشگاه فردوسی مشهد از جمله سدف و پویا می باشند.

میکروسرویس

تمامی درخواست ها برای بازیابی و تغییر داده ها از طریق کلاینت های سمت پویا و سدف  و یا هر پورتال دیگر به این میکروسرویس ارسال می شود و پاسخ مناسب برای هر درخواست تولید و به کلاینت فراخواننده ارسال می شود.

ساختار کدهای سمت میکروسرویس به صورت زیر می باشد:

کدهای مشترک

  • در شاخه microservice یک شاخه با نام core وجود دارد که شامل فایل config و تمامی کلاس های پایه و اصلی می باشد.
  • تنظیمات دیتابیس در core/config.php قرار دارد. در فایل ProjectName/composer.json این تنظیمات autoload شده اند.

"autoload": {

    "files": ["../core/config.php"]

}

  • در شاخه core/DataLayer یک کلاس با نام PdoDataAccess.php دارد که تمای مدل های شاخه ProjectName/app/src/api/Models از آن extend می شوند. این کلاس جهت یکسان سازی دسترسی به دیتابیس ها و انجام برخی از چک های امنیتی در سامانه های دانشگاه فردوسی مشهد تهیه شده است.
  • نوع خصیصه ها در کلاسهای مدل می بایست بر اساس نوع تعریف شده در کلاس core/DataLayer/DataMember مشخص شود.

class A extends PdoDataAccess {

    public $id;

    public $code;

 

    public function __construct($id =null){

        $this->id= DataMember::CreateDMA(DataMember::Pattern_Num);

        $this->code= DataMember::CreateDMA(DataMember::Pattern_Num);

    }

}

  • در فراخوانی میکروسرویس ها از سمت کلاینت های سامانه پویا و سدف برخی از اطلاعات مورد نیاز کاربران در هدر درخواست های http قرار گرفته و به سمت سرور ارسال می شود مانند user-id و ...درکلاس core/Http/HeaderKey این فیلدهای اطلاعاتی به صورت ثوابت (constant) تعریف شده اند تا کدها خواناتر و ساخت یافته تر شوند.

class HeaderKey {

    const PERSON_ID = "PERSON-ID"; شناسه فرد در پورتال های دانشگاه فردوسی اعم از سدف یا پویا

    const IP_ADDRESS = "IP-ADDRESS"; آدرس IP

    const SYS_KEY = "SYS-KEY";

    const USER_ROLES = "USER-ROLES"; نقش کاربر که در پورتال های دانشگاه

    const USER_ID = "USER-ID"; شناسه کاربری شخص

    const H_TOKEN = "H-TOKEN";

    /**

     * @return array

     * @throws ReflectionException

     */

    static function getConstants() {

        $oClass = new ReflectionClass(__CLASS__);

        return $oClass->getConstants();

    }

}

  • کنترلهای لازم بر روی اطلاعات ارسالی از طریق  هدر درخواستها در middleware انجام می شود. برای این منظور کلاس core/Http/HeaderControl.php طراحی شده است که متدهای آن در فایل middleware.php فراخوانی می شوند تا کنترلهای لازم را انجام دهند.
  • سایر کلاس های شاخه core/Http عبارتند از:
  • HttpStatusCodes.php : کدهای وضعیت HTTP در این کلاس به صورت ثوابتی با کد عددی و توضیحات مربوط به آن تعریف شده اند تا در ایجاد پاسخ های http از این کلاس برای تعیین کد وضعیت مناسب استفاده شود.
  • ResponseHelper.php: سه متد برای ایجاد پاسخ های http در سه حالت Successful, Failure و Exception دارد.

class ResponseHelper {

    public static function createSuccessfulResponse(Response $response, $data = null) {...}

    public static function createFailureResponse(Response $response, $httpStatus, $error = null){...}

    public static function createFailureResponseByException(Response $response, $errorMessage) {...}

}

  • HttpResponse.php: متدهاي لازم براي فراخواني Api ها و كار با پاسخ هاي http در اين كلاس پياده سازي شده اند. لطفا براي فراخواني ميكروسرويس هاي در سمت كلاينت از متد CallService كه در اين كلاس پياده سازي شده است استفاده كنيد. اين كلاس بر پايه پكيج Guzzle نوشته شده است كه ابزاري جهت فراخواني REST API ها مي باشد. نمونه فراخواني هاي اين كلاس در شاخه microservices در مخزن microservice/core گيت دانشگاه موجود مي باشد.

کدهای اختصاصی پروژه بر اساس میکروفریم ورک اسلیم

  • با استفاده از کامپوزر میکروفریم ورک اسلیم را نصب و ساختار زیر را ایجاد کرده ایم.

/

├──app/

│   ├── src/

│   │       └── api/

│   │                ├── Models/

│   │                ├── Controllers/

│   │                └── Services(Classes)

│   ├── tests

│   ├── dependencies.php

│   ├── middleware.php

│   ├── routes.php

│   └── settings.php

├──public/

│  ├── css/

│  ├── js/

│  └── index.php

├──vendor/

├──composer.json

└──composer.lock

  • نقطه ورود به اپلیکیشن فایل index.php است که در شاخه public قرار گرفته است. سایر کدهای پروژه در شاخه app قرارد دارند. تمامی بسته هایی که با استفاده از کامپوزر نصب می شوند در شاخه vendor قرار می گیرند.
  • تنظیمات کامپوزر در فایل composer.json قرار گرفته است و برای نگاشت namespaceها به محل درست قرار گیری کلاس ها در روی هارد حتما در فایل composer.json تنظیمات مربوط به psr-4 اضافه شود.

"psr-4": {

   "Api\\": "src/api/"

}

  • در شاخه app شاخه src و چهار فایل زیر قرار گرفته اند:
  1. dependencies.php: تزریق وابستگی ها (DI) و سرویسهایی که در کانتینر تعریف می کنیم در این فایل قرار می گیرند. فایلdependencies.php در فایلrequire ، index.php شده است.
  2.  :middleware.php: میان افزارهای سامانه همگی در این فایل تعریف شده اند.
  3.  :routes.php:  فایل route.php در فایل require ، index.php شده است و شامل تمامی  route هایی است که برای پروژه تعریف شده اند. routeها را می توان بر اساس اشتراکاتی که دارند گروهبندی کرد. به عنوان مثال  تمامی routeهایی که شامل آپلود فایل هستند در یک گروه قرار داده شده و میان افزار فیلتر فایل بر روی همه آنها اعمال شود.
  4. settings.php: آرایه settings در فایل settings.php مقدار داده شده است این آرایه در فایل require ، index.php می شود و اگر به عنوان ورودی در هنگام ایجاد شیء از کلاس Slim\App به آن ارسال شود مقادیر آن با عنوان settings در کانتینر ذخیره می شود.
  • در شاخه src دو شاخه api و tests وجود دارند که شاخه tests برای نوشتن unit test های پروژه با استفاده از phpUnit ایجاد شده است تا از این به بعد برای توسعه نرم افزار روش TDD استفاده شود.
  • در شاخه api تا به اینجا سه زیر شاخه وجود دارند که عبارتند از:
  1. Classes و یا Services: کلاسهای عمومی پروژه مانند کلاس های که متدهای untility را پیاده سازی می کنند در این شاخه قرار دارند.
  2. Controllers: کلاسهای کنترلر در این شاخه قرار دارند.
  3. Models: کلاسهای Model که در واقع هر یک متناظر با یک جدول در پایگاه داده هستند و از کلاس PdoDataAccess مشتق می شوند در این شاخه قرار دارند.

سمت کلاینت

  • جهت مطابقت با استانداردهای جدید php همانند استفاده از PSR-4 برای autoloading، بهتر است  از کامپوزر استفاده شود.
  • تنظیمات کامپوزر در فایل composer.json قرار دارد. کلاس هایی که دارای namespace هستند در بخش autoload در قسمت psr-4 و کلاس هایی که namespace ندارند در قسمت classmap قرار می گیرند.

{

  "name": "fum/test",

  "license": "FUM",

  "authors": [

    {

        "name": "Developer-1",

        "role": "Developer"

    }

  ],

  "require": {

      "php": ">=5.5.0"

  },

  "autoload": {

      "psr-4": {

        "NameSpace1\\": "",

        "NameSpace2\\": "../UI/class2/"

      },

      "classmap": ["../shares", "../sharedClasses"]

  }

}

  • با استفاده از کامپوزر دیگر نیازی به include کردن کلاس ها نیست و فقط کافی است تا فایل vendor/autoload.php در ابتدای فایلی که می خواهیم در آن به کلاس ها دسترسی داشته باشیم require شود. برای کلاس هایی که دارای namespace هستند یا باید هنگام ایجاد شیء namespace آنها را به طور کامل ذکر کنیم یا با استفاده از کلمه کلیدی use فضای نام آنها را به مفسر php اعلام کنیم تا بتوانیم بدون ذکر فضای نام کامل از آنها شیء ایجاد کنیم.

require_once __DIR__.'/vendor/autoload.php';

use NameSpace1\Class1;

use NameSpace1\Class2;

کدهای مشترک

  • کلاس های شاخه PFBC که المانهای درون فرم را به صورت bootstrap ای پیاده سازی می کند. این کلاس جهت تسهیل ایجاد رابط کاربری نوشته شده است و برای انجام تغییرات در آینده قابل توسعه می باشد. این شاخه به همراه تمامی فونت ها، تصاویر و استایل های آن در مسیر shares/UI در مخزن  قرار داده شده است.
  • جهت فراخوانی APIها ازمتد های کلاس HttpResponse موجود در شاخه shares/Http استفاده می کنیم.

$response = new HttpResponse(APIConstants::getSalt());

$response->CallService(HttpResponse::METHOD_GET, API_URL, $params);

$result = $response->getResult();

 

 

کدهای اختصاصی

در شاخه ProjectName/classes سه فایل قرار دارد:

  • APIConstant.php:  تمامی URL های API ها به صورت ثوابت در آن تعریف شده است. برای پروژه های مشابه بهتر است کلاس مشابه ای ایجاد شود تا کد مرتب تر و ساخت یافته تری تولید شود.