隨著雲端運算和微服務架構的流行,API網關作為微服務系統中不可或缺的一部分,其功能變得越來越重要。 API閘道可以攔截並轉送所有進出系統的請求,並負責安全性、存取控制、流量控制和負載平衡等功能。
在本文中,我們將介紹如何使用PHP7.0實作一個簡單的API網關,以實現以下功能:
在開始之前,請確保已安裝以下軟體:
步驟1:寫基本的API網關
首先,我們需要建立一個基本的API網關,用於路由請求到微服務。我們將使用Symfony Routing Component來處理路由。
建立一個新的PHP文件,例如index.php,並添加以下程式碼:
require_once 'vendor/autoload.php'; use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpFoundationResponse; use SymfonyComponentRoutingMatcherUrlMatcher; use SymfonyComponentRoutingExceptionResourceNotFoundException; $routes = new RouteCollection(); $routes->add('hello', new Route('/hello/{name}', array( 'controller' => function ($request) { return new Response(sprintf("Hello, %s!", $request->attributes->get('name'))); } ))); $matcher = new UrlMatcher($routes, getRequest()); try { $request = Request::createFromGlobals(); $parameters = $matcher->matchRequest($request); $response = call_user_func($parameters['controller'], $request); } catch (ResourceNotFoundException $exception) { $response = new Response('Not Found', Response::HTTP_NOT_FOUND); } catch (Exception $exception) { $response = new Response('An error occurred', Response::HTTP_INTERNAL_SERVER_ERROR); } $response->send();
在此程式碼中,我們建立了一個名為“hello”的路由,該路由將請求轉送到一個匿名控制器方法中。當處理此路由時,它將在回應中傳回「Hello,{name}!」其中{name}是路由參數。
我們使用Symfony的Request和Response類別來建立和傳送HTTP請求和回應。 Symfony的Routing元件負責路由請求到匹配的路由,並呼叫匹配的控制器方法。
此時,我們可以執行此文件,造訪http://localhost:8080/hello/world,便可以看到輸出「Hello,world!」。
步驟2:新增限流功能
我們希望API閘道能夠對每個API的請求進行限制,以減輕服務端的過載風險。為此,我們可以使用Redis來儲存每個API的限流計數器。
首先,我們需要使用Composer安裝Predis,這是PHP中的一個Redis客戶端程式庫:
composer require predis/predis
然後,在index.php中加入以下程式碼,以便在每次微服務請求之前檢查計數器:
use PredisClient; // ... $redis = new Client(); // Limit requests to 100 per minute per user. $maxRequests = 100; $timeWindow = 60; // seconds $ip = $_SERVER['REMOTE_ADDR']; $key = "ratelimit:{$ip}"; $currentRequests = $redis->incr($key); $redis->expire($key, $timeWindow); if ($currentRequests > $maxRequests) { $response = new Response('Rate limit exceeded', Response::HTTP_TOO_MANY_REQUESTS); $response->headers->set('Retry-After', $timeWindow); $response->send(); exit; }
在此程式碼中,我們使用Predis客戶端連接到Redis伺服器,並使用每個請求的IP位址作為鍵名。我們設定了每個使用者每分鐘100個請求的限制,並使用Incr函數遞增計數器。
如果計數器目前值超過最大限制,則傳回HTTP 429「Too Many Requests」回應,並設定「Retry-After」頭,以通知客戶端何時再次嘗試請求。
步驟3:新增認證和授權功能
我們還需要為每個API請求新增基本的認證和授權功能。為此,我們將使用JSON Web Token(JWT)標準。
若要使用JWT,請先安裝firebase / php-jwt函式庫:
composer require firebase/php-jwt
然後,在index.php中加入以下程式碼,以實作JWT標準的認證與授權:
use FirebaseJWTJWT; // ... $key = 'secret'; $token = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; if ($token) { try { $decoded = JWT::decode($token, $key, array('HS256')); $user_id = $decoded->sub; $roles = $decoded->roles; } catch (Exception $e) { $response = new Response('Invalid token', Response::HTTP_UNAUTHORIZED); $response->send(); exit; } // Check user roles and permissions here... } else { $response = new Response('Token required', Response::HTTP_UNAUTHORIZED); $response->send(); exit; }
在此程式碼中,我們使用從HTTP標頭中提取的JWT令牌來識別和驗證請求的身份。我們使用JWT庫對令牌進行解碼,並驗證簽名和有效性。如果令牌有效,則從中提取使用者ID和角色訊息,並檢查其權限。如果令牌無效,則傳回HTTP 401「Unauthorized」回應。
步驟4:新增統計功能
最後,我們新增一個簡單的統計功能,以記錄API的使用情況。為此,我們將使用Redis來儲存請求次數和回應時間等指標。
首先,我們需要安裝phpredis擴充功能:
sudo apt-get install php7.0-redis
然後,在index.php中加入以下程式碼,以記錄每個請求的統計資料:
use PredisClient; // ... $redis = new Client(); $ip = $_SERVER['REMOTE_ADDR']; $key = "stats:{$ip}"; $now = time(); $timestamp = strtotime(date('Y-m-d H:i:00', $now)); $redis->zincrby($key, 1, $timestamp); $redis->expire($key, 3600);
在此在程式碼中,我們考慮每個IP位址(即每個使用者)的請求次數,並使用Redis的ZINCRBY指令將請求計數器的值增加1。我們也使用在Redis中設定過期時間來刪除過期的記錄。
步驟5:部署API網關
現在,我們已經為我們的API網關添加了路由、限制、認證、授權和統計等基本功能。我們可以使用Apache或Nginx等傳統的Web伺服器來部署它,或使用PHP內建伺服器進行測試。
首先,在終端機中執行以下命令,以便啟動PHP內建伺服器並將其指向我們的index.php檔案:
php -S localhost:8080
然後,我們可以在瀏覽器中存取http:/ /localhost:8080/,並在URL路徑中新增/hello/world等路由,以測試API網關的各種功能。
總結
在這篇文章中,我們使用PHP7.0和各種開源程式庫來實現一個基本的API網關,並添加了限制、認證、授權和統計等基本功能。 API網關是微服務架構不可或缺的一部分,它可以幫助我們實現更好的效能、安全性和可擴展性。
實際上,現在有許多強大的API網關解決方案可供選擇,例如Kong、Tyk、AWS API Gateway等,它們提供了更多的高級功能和集成,如負載平衡、快取、安全性、監視和管理等。
但是,了解如何使用PHP和Symfony等函式庫來建立API網關仍然是有價值的,當需要快速建立一個簡單的API網關時,這是一個極好的選擇。
以上是如何使用PHP7.0實作一個微服務架構的API網關?的詳細內容。更多資訊請關注PHP中文網其他相關文章!