API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
API Gateway получает клиентские запросы, направляет их в соответствующий микросервис, а затем возвращает ответ сервера клиенту.
Шлюз отвечает за такие задачи, как маршрутизация, аутентификация и ограничение скорости. Это позволяет микросервисам сосредоточиться на своих индивидуальных задачах и повышает общую производительность и масштабируемость системы.
Тогда мы можем сказать в двух словах: "API-шлюз - это инструмент управления API, который находится между клиентом и набором бэкенд-сервисов".
Большинство корпоративных API развертываются через API-шлюзы. Обычно API-шлюзы выполняют общие задачи, которые используются в системе API-сервисов, такие как аутентификация пользователей, ограничение скорости и статистика.
В самом простом виде API-сервис принимает удаленный запрос и возвращает ответ. Но в реальной жизни все не так просто. Рассмотрим различные проблемы, возникающие при размещении крупномасштабных API.
Сложность заключается в том, чтобы предложить вашим клиентам простой и надежный опыт работы в условиях всей этой сложности. API-шлюз - это способ отделить клиентский интерфейс от реализации бэкенда. Когда клиент делает запрос, API-шлюз разбивает его на несколько запросов, направляет их в нужные места, выдает ответ и все отслеживает.
𝗥𝗼𝘂𝘁𝗶𝗻𝗴: API-шлюз получает запросы от клиентов и направляет их в соответствующий микросервис. Это позволяет клиентам получать доступ к различным микросервисам через единую точку входа, упрощая общий дизайн системы.
𝗦𝗲𝗰𝘂𝗿𝗶𝘁𝘆 API-шлюз может использоваться для аутентификации клиентов и применения политик контроля доступа к микросервисам. Это помогает обеспечить доступ к микросервисам только авторизованным клиентам и предотвратить несанкционированный доступ.
𝐓𝐫𝐚𝐧𝐬𝐟𝐨𝐫𝐦𝗶𝗻𝗴 𝐫𝐞𝐪𝐮𝐞𝐬𝐭𝐬 𝐚𝐧𝐝 𝐫𝐞𝐬𝐩𝐨𝐧𝐬𝐞𝐬: API Gateway может преобразовывать входящие запросы и исходящие ответы на бэкенд и из бэкенда для удовлетворения потребностей различных клиентов или соответствия различным архитектурам бэкенда.
𝗥𝗮𝘁𝗲𝗹𝗶𝗺𝗶𝘁𝗶𝗻𝗴: Вы можете ограничить доступ клиентов к микросервисам с помощью шлюза API. Это поможет предотвратить атаки типа "отказ в обслуживании" и другие виды вредоносного поведения.
𝗟𝗼𝗮𝗱𝗯𝗮𝗹𝗮𝗻𝗰𝗶𝗻𝗴: API Gateway может распределять входящие запросы между несколькими экземплярами микросервиса, позволяя системе обрабатывать большее количество запросов и повышая общую производительность и масштабируемость.
𝗖𝗮𝗰𝗵𝗶𝗻𝗴: Шлюз API может кэшировать ответы микросервисов, уменьшая количество запросов, которые необходимо перенаправлять микросервисам, и повышая общую производительность системы.
𝗦𝗲𝗿𝘃𝗲𝗿𝗹𝗲𝘀𝘀𝗲𝘅𝗲𝗰𝘂𝘁𝗶𝗼𝗻: API Gateway может интегрироваться с другими сервисами, такими как AWS Lambda, для создания бессерверных архитектур и обеспечения сложной обработки запросов без необходимости использования выделенного сервера.
𝗖𝗶𝗿𝗰𝘂𝗶𝘁 𝗯𝗿𝗲𝗮𝗸𝗲𝗿: API Gateway можно использовать для реализации схем автоматического выключателя, что поможет защитить от каскадных сбоев и повысить отказоустойчивость вашей системы.
𝗥𝗲𝘃𝗲𝗿𝘀𝗲𝗽𝗿𝗼𝘅𝘆: API Gateway может действовать как обратный прокси-сервер, направляя входящие запросы в соответствующую внутреннюю службу на основе пути запроса или других критериев.
𝗔𝗣𝗜 𝘃𝗲𝗿𝘀𝗶𝗼𝗻𝗶𝗻𝗴: API Gateway можно использовать для реализации версионности API, что позволяет поддерживать несколько версий API и управлять переходом от одной версии к другой.
Попытаюсь объяснить на базовом примере для API.
Допустим, у вас есть 3 микросервиса:
Я предполагаю, что вы используете http Only cookie для хранения токена пользователя.
В микросервисе Core у меня такая структура маршрута:
Route::prefix('core')->group(function () { Route::post('register', [AuthController::class, 'register']); Route::post('login', [AuthController::class, 'login']); Route::middleware('scope.trader')->group(function () { Route::get('user', [AuthController::class, 'user']); }); });
Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.
Итак, в дополнение к получению результата, я должен создать сервис для пользователя, и вот как я это сделал:
UserService : class UserService extends ApiService { public function __construct() { // Get User Endpoint Microservice API URL $this->endpoint = env('USERS_MS') . '/api'; } } ApiService : abstract class ApiService { protected string $endpoint; public function request($method, $path, $data = []) { $response = $this->getRequest($method, $path, $data); if ($response->ok()) {return $response->json();}; throw new HttpException($response->status(), $response->body()); } public function getRequest($method, $path, $data = []) { return \Http::acceptJson()->withHeaders([ 'Authorization' => 'Bearer ' . request()->cookie('token') ])->$method("{$this->endpoint}/{$path}", $data); } public function post($path, $data) { return $this->request('post', $path, $data); } public function get($path) { return $this->request('get', $path); } public function put($path, $data) { return $this->request('put', $path, $data); } public function delete($path) { return $this->request('delete', $path); } }
'попытаюсь объяснить на базовом примере для API.
Допустим, у вас есть 3 микросервиса:
Я предполагаю, что вы используете httpOnly cookie для хранения токена пользователя.
В микросервисе Core у меня такая структура маршрута:
Route::prefix('core')->group(function () { Route::post('register', [AuthController::class, 'register']); Route::post('login', [AuthController::class, 'login']);
Route::middleware('scope.trader')->group(function () { Route::get('user', [AuthController::class, 'user']);
}); });
Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.
Поэтому, чтобы получить результат, я должен создать сервис для пользователя, и вот как я это сделал:
UserService : class UserService extends ApiService { public function __construct() { // Get User Endpoint Microservice API URL $this->endpoint = env('USERS_MS') . '/api'; } } ApiService : abstract class ApiService { protected string $endpoint;
public function request($method, $path, $data = []) { $response = $this->getRequest($method, $path, $data);
if ($response->ok()) {return $response->json();};
throw new HttpException($response->status(), $response->body()); }
public function getRequest($method, $path, $data = []) { return \Http::acceptJson()->withHeaders([ 'Authorization' => 'Bearer ' . request()->cookie('token') ])->$method("{$this->endpoint}/{$path}", $data); }
public function post($path, $data) { return $this->request('post', $path, $data); }
public function get($path) { return $this->request('get', $path); }
public function put($path, $data) { return $this->request('put', $path, $data); }
public function delete($path) { return $this->request('delete', $path); } }
Если вам интересно, откуда взялся этот UserService, то я должен сказать, что я создал пакет для использования его в других микросервисах, так что вы можете сделать то же самое или просто создать сервис и использовать его в своих микросервисах или т.д.
Про ApiService все очевидно, но я постараюсь объяснить основу.
Итак, если мы хотим использовать это, мы можем просто сделать вот так в нашем контроллере:
class AuthController extends Controller { // use Services\UserService; public UserService $userService; /** * @param UserService $userService */ public function __construct(UserService $userService) { $this->userService = $userService; } public function register(RegisterRequest $request) { $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ]; // additional fields can be used for something except from request and // optional, like is it admin or user or etc. // call the post method, pass the endpoint url(`register`), pass $data $user = $this->userService->post('register', $data); // get data from target endpoint // and ... return response($user, Response::HTTP_CREATED); } public function login(Request $request) { // same thing here again, but this time i passed scope to help me // get the specific user scope $data = $request->only('email', 'password') + ['scope' => 'writer']; $response = $this->userService->post('login', $data); // as you can see when user do success login, we will get token, // which i got that token using Passport and set it to $cookie $cookie = cookie('token', $response['token'], 60 * 24); // 1 day // then will set a new httpOnly token on response. return response([ 'message' => 'success' ])->withCookie($cookie); } public function user(Request $request) { // Here, base on userService as you saw, we passed token in all requests // which if token exist, we get the result, since we're expecting // token to send back the user informations. $user = $this->userService->get('user'); // get posts belong to authenticated user $posts = Post::where('user_id', $user['id'])->get(); $user['posts'] = $posts; return $user; } }
'попытаюсь объяснить на базовом примере для API.
Допустим, у вас есть 3 микросервиса:
Я предполагаю, что вы используете httpOnly cookie для хранения токена пользователя.
В микросервисе Core у меня такая структура маршрута:
Route::prefix('core')->group(function () { Route::post('register', [AuthController::class, 'register']); Route::post('login', [AuthController::class, 'login']);
Route::middleware('scope.trader')->group(function () { Route::get('user', [AuthController::class, 'user']);
}); });
Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.
Итак, чтобы получить результат, я должен создать сервис для пользователя, и вот как я это сделал:
UserService : class UserService extends ApiService { public function __construct() { // Get User Endpoint Microservice API URL $this->endpoint = env('USERS_MS') . '/api'; } } ApiService : abstract class ApiService { protected string $endpoint;
public function request($method, $path, $data = []) { $response = $this->getRequest($method, $path, $data);
if ($response->ok()) {return $response->json();};
throw new HttpException($response->status(), $response->body()); }
public function getRequest($method, $path, $data = []) { return \Http::acceptJson()->withHeaders([ 'Authorization' => 'Bearer ' . request()->cookie('token') ])->$method("{$this->endpoint}/{$path}", $data); }
public function post($path, $data) { return $this->request('post', $path, $data); }
public function get($path) { return $this->request('get', $path); }
public function put($path, $data) { return $this->request('put', $path, $data); }
public function delete($path) { return $this->request('delete', $path); } }
Вы задаетесь вопросом, откуда взялся этот UserService, то я должен сказать, что я создал пакет для использования его в других микросервисах, так что вы можете сделать то же самое или просто создать сервис и использовать его в своих микросервисах или т.д.
Про ApiService все очевидно, но я постараюсь объяснить основу.
Итак, если мы хотим использовать это, мы можем просто сделать вот так в нашем контроллере:
class AuthController extends Controller { // use Services\UserService; public UserService $userService;
/** * @param UserService $userService */ public function __construct(UserService $userService) { $this->userService = $userService; }
public function register(RegisterRequest $request) { $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ]; // additional fields can be used for something except from request and // optional, like is it admin or user or etc.
// call the post method, pass the endpoint url(`register`), pass $data $user = $this->userService->post('register', $data); // get data from target endpoint // and ... return response($user, Response::HTTP_CREATED); }
public function login(Request $request) { // same thing here again, but this time i passed scope to help me // get the specific user scope $data = $request->only('email', 'password') + ['scope' => 'writer'];
$response = $this->userService->post('login', $data); // as you can see when user do success login, we will get token, // which i got that token using Passport and set it to $cookie $cookie = cookie('token', $response['token'], 60 * 24); // 1 day // then will set a new httpOnly token on response. return response([ 'message' => 'success' ])->withCookie($cookie); }
public function user(Request $request) { // Here, base on userService as you saw, we passed token in all requests // which if token exist, we get the result, since we're expecting // token to send back the user informations.
$user = $this->userService->get('user');
// get posts belong to authenticated user $posts = Post::where('user_id', $user['id'])->get();
$user['posts'] = $posts;
return $user; } }
Как насчет пользовательского микросервиса? Ну, здесь все ясно, и он должен работать как базовое приложение.
Вот маршруты:
Route::post('register', [AuthController::class, 'register']); Route::post('login', [AuthController::class, 'login']); Route::middleware(['bunch','of', 'middlewares'])->group( function (){ Route::get('user', [AuthController::class, 'user']); });
А в контроллере :
class AuthController extends Controller { public function register(Request $request) { $user = User::create( $request->only('first_name', 'email', 'additional_field') + ['password' => \Hash::make($request->input('password'))] ); return response($user, Response::HTTP_CREATED); } public function login(Request $request) { if (!\Auth::attempt($request->only('email', 'password'))) { return response([ 'error' => 'user or pass is wrong or whatever.' ], Response::HTTP_UNAUTHORIZED); } $user = \Auth::user(); $jwt = $user->createToken('token', [$request->input('here you can pass the required scope like trader as i expalined in top')])->plainTextToken; return compact('token'); } public function user(Request $request) { return $request->user(); } }
Итак, вот полный пример, и вы можете использовать подход микросервиса Core на других микросервисах для получения информации, связанной с аутентифицированным пользователем, и, как вы видите, все будет аутентифицировано благодаря этим запросам от ядра к другим микросервисам.
Мой список статей в Publis
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.