{"id":1095,"date":"2025-06-12T12:47:59","date_gmt":"2025-06-12T04:47:59","guid":{"rendered":"https:\/\/www.zhaozhao123.cn\/php\/php-application-manual\/symfony\/1095.html"},"modified":"2025-06-12T12:47:59","modified_gmt":"2025-06-12T04:47:59","slug":"%e5%a6%82%e4%bd%95%e5%9c%a8-symfony-%e4%b8%ad%e5%ae%9e%e7%8e%b0%e9%99%90%e6%b5%81%ef%bc%9a%e5%ae%8c%e6%95%b4%e6%8c%87%e5%8d%97","status":"publish","type":"my1js","link":"https:\/\/www.zhaozhao123.cn\/php\/my1js\/1095.html","title":{"rendered":"\u5982\u4f55\u5728 Symfony \u4e2d\u5b9e\u73b0\u9650\u6d41\uff1a\u5b8c\u6574\u6307\u5357"},"content":{"rendered":"<div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--1\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/dyA-1-400x300.jpg\" alt=\"Bug&#32534;&#35793;&#29422;\" class=\"wp-image-1842\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">Bug&#32534;&#35793;&#29422;<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<p>&#22312; Symfony &#20013;&#23454;&#29616;&#38480;&#27969;&#65288;Rate Limiting&#65289;&#21487;&#20197;&#36890;&#36807;&#22810;&#31181;&#26041;&#24335;&#26469;&#23436;&#25104;&#65292;&#21253;&#25324;&#20351;&#29992;&#31532;&#19977;&#26041;&#24211;&#12289;&#33258;&#23450;&#20041;&#23454;&#29616;&#25110;&#32773;&#32467;&#21512;&#20854;&#20182;&#20013;&#38388;&#20214;&#21644;&#24037;&#20855;&#12290;&#20197;&#19979;&#26159;&#19968;&#20010;&#23436;&#25972;&#30340;&#25351;&#21335;&#65292;&#23637;&#31034;&#22914;&#20309;&#22312; Symfony &#20013;&#23454;&#29616;&#38480;&#27969;&#12290;<\/p>\n<h3>1. &#23433;&#35013;&#24182;&#37197;&#32622; Redis<\/h3>\n<p>&#39318;&#20808;&#65292;&#20320;&#38656;&#35201;&#23433;&#35013; Redis &#24182;&#23558;&#20854;&#37197;&#32622;&#20026;&#20320;&#30340;&#24212;&#29992;&#30340;&#32531;&#23384;&#31995;&#32479;&#12290;&#20320;&#21487;&#20197;&#36890;&#36807; Composer &#26469;&#23433;&#35013; <code>predis\/predis<\/code> &#24211;&#65306;<\/p>\n<pre><code class=\"language-bash\">composer require predis\/predis<\/code><\/pre>\n<p>&#28982;&#21518;&#65292;&#37197;&#32622; Redis &#22312;&#20320;&#30340; Symfony &#37197;&#32622;&#25991;&#20214;&#20013;&#65306;<\/p>\n<pre><code class=\"language-yaml\"># config\/packages\/cache.yaml\nframework:\n    cache:\n        default_redis_connection: redis.default<\/code><\/pre>\n<h3>2. &#21019;&#24314; Rate Limiter &#23454;&#29616;<\/h3>\n<p>&#25509;&#19979;&#26469;&#65292;&#21019;&#24314;&#19968;&#20010; Rate Limiter &#31867;&#26469;&#31649;&#29702;&#35831;&#27714;&#35745;&#25968;&#21644;&#38480;&#21046;&#26465;&#20214;&#12290;&#20320;&#21487;&#20197;&#20351;&#29992; <code>SymfonyComponentCacheAdapterRedisAdapter<\/code> &#26469;&#19982; Redis &#36827;&#34892;&#20132;&#20114;&#12290;<\/p>\n<pre><code class=\"language-php\">\/\/ src\/Service\/Limiter.php\nnamespace AppService;\n\nuse PredisClient;\nuse PredisPipeline;\n\nclass Limiter\n{\n    private $cache;\n    private $limit;\n    private $period;\n\n    public function __construct(Client $cache, int $limit, int $period)\n    {\n        $this-&gt;cache = $cache;\n        $this-&gt;limit = $limit;\n        $this-&gt;period = $period;\n    }\n\n    public function isAllowed($key): bool\n    {\n        \/\/ &#33719;&#21462;&#24403;&#21069;&#26102;&#38388;&#25139;\n        $timestamp = time();\n\n        \/\/ &#32531;&#23384;&#38190;&#21517;\n        $cacheKey = \"rate_limit:$key\";\n\n        \/\/ &#33719;&#21462;&#19978;&#27425;&#35775;&#38382;&#30340;&#26102;&#38388;&#25139;\n        $lastAccessTimestamp = $this-&gt;cache-&gt;get($cacheKey);\n\n        \/\/ &#22914;&#26524;&#27809;&#26377;&#35760;&#24405;&#65292;&#30452;&#25509;&#20801;&#35768;&#35775;&#38382;\n        if (!$lastAccessTimestamp) {\n            $this-&gt;cache-&gt;set($cacheKey, $timestamp, ['ttl' =&gt; $this-&gt;period]);\n            return true;\n        }\n\n        \/\/ &#35745;&#31639;&#20801;&#35768;&#30340;&#26368;&#22823;&#35775;&#38382;&#27425;&#25968;\n        $maxAllowedRequests = $this-&gt;limit \/ ($this-&gt;period \/ 60); \/\/ &#27599;&#20998;&#38047;&#26368;&#22810;&#20801;&#35768;&#22810;&#23569;&#27425;\n\n        \/\/ &#35745;&#31639;&#20801;&#35768;&#30340;&#26368;&#22823;&#35775;&#38382;&#38388;&#38548;\n        $maxInterval = (int) (($this-&gt;period \/ 60) * 60); \/\/ &#27599;&#20998;&#38047;&#26368;&#22810;&#20801;&#35768;&#22810;&#38271;&#26102;&#38388;&#38388;&#38548;&#19968;&#27425;\n\n        \/\/ &#35745;&#31639;&#24403;&#21069;&#20801;&#35768;&#30340;&#26368;&#22823;&#35775;&#38382;&#27425;&#25968;\n        $currentAllowedRequests = min($maxAllowedRequests, ($timestamp - $lastAccessTimestamp) \/ $maxInterval);\n\n        \/\/ &#22914;&#26524;&#24403;&#21069;&#20801;&#35768;&#30340;&#26368;&#22823;&#35775;&#38382;&#27425;&#25968;&#22823;&#20110;&#38646;&#65292;&#21017;&#20801;&#35768;&#35775;&#38382;\n        if ($currentAllowedRequests &gt; 0) {\n            $this-&gt;cache-&gt;set($cacheKey, $timestamp, ['ttl' =&gt; $this-&gt;period]);\n            return true;\n        }\n\n        return false;\n    }\n}<\/code><\/pre>\n<h3>3. &#20351;&#29992; Rate Limiter<\/h3>\n<p>&#29616;&#22312;&#65292;&#20320;&#21487;&#20197;&#20351;&#29992;&#36825;&#20010; Rate Limiter &#26469;&#20445;&#25252;&#20320;&#30340; API &#31471;&#28857;&#12290;&#20363;&#22914;&#65292;&#20551;&#35774;&#20320;&#26377;&#19968;&#20010;&#31616;&#21333;&#30340;&#25511;&#21046;&#22120;&#26041;&#27861;&#65306;<\/p>\n<pre><code class=\"language-php\">\/\/ src\/Controller\/ApiController.php\nnamespace AppController;\n\nuse AppServiceLimiter;\nuse SymfonyBundleFrameworkBundleControllerAbstractController;\nuse SymfonyComponentHttpFoundationRequest;\nuse SymfonyComponentHttpFoundationResponse;\n\nclass ApiController extends AbstractController\n{\n    private $limiter;\n\n    public function __construct(Limiter $limiter)\n    {\n        $this-&gt;limiter = $limiter;\n    }\n\n    \/**\n     * @param Request $request\n     * @return Response\n     *\/\n    public function index(Request $request): Response\n    {\n        $key = 'api_key'; \/\/ &#26367;&#25442;&#20026;&#23454;&#38469;&#30340; API &#38190;\n\n        if (!$this-&gt;limiter-&gt;isAllowed($key)) {\n            return new Response('Too many requests', Response::HTTP_TOO_MANY_REQUESTS);\n        }\n\n        \/\/ &#22788;&#29702;&#35831;&#27714;&#36923;&#36753;\n        return new Response('Success');\n    }\n}<\/code><\/pre>\n<h3>4. &#37197;&#32622;&#36335;&#30001;&#21644;&#38450;&#28779;&#22681;<\/h3>\n<p>&#26368;&#21518;&#65292;&#30830;&#20445;&#20320;&#30340;&#36335;&#30001;&#21644;&#38450;&#28779;&#22681;&#37197;&#32622;&#27491;&#30830;&#65292;&#24182;&#19988;&#33021;&#22815;&#35843;&#29992;&#20320;&#30340; Rate Limiter &#26041;&#27861;&#12290;<\/p>\n<pre><code class=\"language-yaml\"># config\/routes.yaml\napp_api:\n    path: '\/api'\n    controller: AppControllerApiController::index\n    methods: [GET]\n    defaults:\n        _controller: AppControllerApiController::index\n        key: 'your_api_key' # &#26367;&#25442;&#20026;&#23454;&#38469;&#30340; API &#38190;<\/code><\/pre>\n<p>&#36890;&#36807;&#20197;&#19978;&#27493;&#39588;&#65292;&#20320;&#21487;&#20197;&#22312; Symfony &#20013;&#25104;&#21151;&#23454;&#29616;&#38480;&#27969;&#21151;&#33021;&#12290;&#26681;&#25454;&#20320;&#30340;&#20855;&#20307;&#38656;&#27714;&#65292;&#20320;&#21487;&#33021;&#38656;&#35201;&#35843;&#25972; Rate Limiter &#30340;&#21442;&#25968;&#21644;&#36923;&#36753;&#12290;<\/p>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div><div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--2\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/zp-400x300.jpg\" alt=\"&#40657;&#26495;Bug&#35762;&#24072;\" class=\"wp-image-1849\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">&#40657;&#26495;Bug&#35762;&#24072;<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<body><h2>&#20171;&#32461;<\/h2><p>&#38480;&#27969;&#26159;Web&#24212;&#29992;&#24320;&#21457;&#20013;&#30340;&#19968;&#20010;&#37325;&#35201;&#26041;&#38754;&#65292;&#23427;&#36890;&#36807;&#38480;&#21046;&#29992;&#25143;&#22312;&#19968;&#23450;&#26102;&#38388;&#20869;&#21457;&#20986;&#30340;&#35831;&#27714;&#25968;&#37327;&#26469;&#20445;&#25252;API&#65292;&#20174;&#32780;&#38450;&#27490;&#34987;&#28389;&#29992;&#12290;&#22312;Symfony&#20013;&#23454;&#29616;&#38480;&#27969;&#21487;&#20197;&#25552;&#39640;&#24212;&#29992;&#31243;&#24207;&#30340;&#31283;&#23450;&#24615;&#21644;&#21487;&#38752;&#24615;&#12290;<\/p><p>&#26412;&#25351;&#21335;&#23558;&#24341;&#23548;&#24744;&#36890;&#36807;&#19968;&#31995;&#21015;&#27493;&#39588;&#65292;&#20197;&#26377;&#25928;&#25972;&#21512;&#36895;&#29575;&#38480;&#21046;&#21040;&#24744;&#30340;Symfony&#39033;&#30446;&#20013;&#12290;&#25105;&#20204;&#36824;&#23558;&#25506;&#35752;&#20195;&#30721;&#31034;&#20363;&#65292;&#20197;&#20415;&#26356;&#22909;&#22320;&#29702;&#35299;&#27010;&#24565;&#12290;<\/p><h2>&#29702;&#35299;&#38480;&#27969;<\/h2><p>&#22312;&#25105;&#20204;&#28145;&#20837;&#25216;&#26415;&#32454;&#33410;&#20043;&#21069;&#65292;&#29702;&#35299;&#20160;&#20040;&#26159;&#36895;&#29575;&#38480;&#21046;&#20197;&#21450;&#20026;&#20160;&#20040;&#23427;&#24456;&#37325;&#35201;&#33267;&#20851;&#37325;&#35201;&#12290;&#36895;&#29575;&#38480;&#21046;&#36890;&#36807;&#38480;&#21046;&#23458;&#25143;&#31471;&#22312;&#32473;&#23450;&#26102;&#38388;&#20869;&#23545;API&#25110;&#26381;&#21153;&#30340;&#35831;&#27714;&#25968;&#37327;&#26469;&#23454;&#29616;&#12290;&#36825;&#23545;&#20110;&#38450;&#27490;&#28389;&#29992;&#12289;&#33410;&#32422;&#26381;&#21153;&#22120;&#36164;&#28304;&#21644;&#26377;&#25928;&#31649;&#29702;&#27969;&#37327;&#38750;&#24120;&#26377;&#29992;&#12290;<\/p><h2>&#36873;&#25321;&#31574;&#30053;<\/h2><p>&#26377;&#20960;&#31181;&#31574;&#30053;&#21487;&#20197;&#29992;&#20110;&#36895;&#29575;&#38480;&#21046;&#65292;&#20363;&#22914;&#22266;&#23450;&#31383;&#21475;&#12289;&#28369;&#21160;&#31383;&#21475;&#21644;&#20196;&#29260;&#26742;&#12290;&#35831;&#26681;&#25454;&#24744;&#30340;&#24212;&#29992;&#38656;&#27714;&#36873;&#25321;&#19968;&#20010;&#12290;&#22312;&#24320;&#22987;&#20043;&#21069;&#65292;&#35831;&#30830;&#20445;&#24744;&#24050;&#32463;&#28385;&#36275;&#20197;&#19979;&#20808;&#20915;&#26465;&#20214;&#65306;<\/p><p>&#29087;&#24713;Composer<\/p><p>&#29702;&#35299;PHP&#32534;&#31243;<\/p><p>The Symfony framework has been installed.<\/p><h2>&#22312;Symfony&#20013;&#23454;&#29616;&#38480;&#27969;&#21151;&#33021;&#12290;<\/h2><p>&#19968;&#31181;&#22312;Symfony&#20013;&#23454;&#29616;&#36895;&#29575;&#38480;&#21046;&#30340;&#26041;&#27861;&#26159;&#20351;&#29992;&ldquo;symfony\/rate-limiter&rdquo;&#32452;&#20214;&#12290;&#35753;&#25105;&#20204;&#30475;&#30475;&#22914;&#20309;&#38598;&#25104;&#23427;&#65306;<\/p><pre><code>composer require symfony\/rate-limiter<\/code><\/pre><p>&#23433;&#35013;&#36895;&#29575;&#38480;&#21046;&#32452;&#20214;&#21518;&#65292;&#38656;&#35201;&#37197;&#32622;&#23427;&#12290;&#21487;&#20197;&#36890;&#36807;&#21019;&#24314;&#19968;&#20010;&#26032;&#30340;&#25991;&#20214;&#26469;&#23436;&#25104;&#36825;&#20010;&#25805;&#20316;&#12290;<\/p><pre><code>\/\/config\/packages\/rate_limiter.yaml\nrate_limiter:\n    anonymous_api:\n        policy: 'token_bucket'\n        limit: 10\n        interval: '1 minute'\n<\/code><\/pre><p>&#35813;&#37197;&#32622;&#35774;&#32622;&#20102;&#19968;&#20010;&#21311;&#21517;API&#65292;&#27599;&#20998;&#38047;&#35831;&#27714;&#27425;&#25968;&#38480;&#21046;&#20026;10&#27425;&#65292;&#20351;&#29992;&#20196;&#29260;&#26742;&#31574;&#30053;&#12290;<\/p><h2>&#21019;&#24314;&#19968;&#20010;&#36895;&#29575;&#38480;&#21046;&#22120;<\/h2><p>&#29616;&#22312;&#65292;&#24744;&#21487;&#20197;&#22312;&#25511;&#21046;&#22120;&#20013;&#21019;&#24314;&#38480;&#27969;&#22120;&#65306;<\/p><pre><code>\/\/ src\/Controller\/ApiLimitController.php\nnamespace AppController;\n\nuse SymfonyComponentRateLimiterRateLimiterFactory;\nuse SymfonyComponentHttpFoundationResponse;\n\nclass ApiLimitController\n{\n    private $rateLimiterFactory;\n\n    public function __construct(RateLimiterFactory $rateLimiterFactory)\n    {\n        $this-&gt;rateLimiterFactory = $rateLimiterFactory;\n    }\n\n    public function index(): Response\n    {\n        $limiter = $this-&gt;rateLimiterFactory-&gt;create($request-&gt;getClientIp());\n\n        if (false === $limiter-&gt;consume(1)-&gt;isAccepted()) {\n            return new Response('Too many requests', 429);\n        }\n\n        \/\/ Your API logic here\n\n        return new Response('API response', 200);\n    }\n}\n<\/code><\/pre><p>&#19978;&#36848;&#20195;&#30721;&#26816;&#26597;&#24403;&#21069;&#35831;&#27714;&#26159;&#21542;&#21487;&#20197;&#36827;&#34892;&#65292;&#32771;&#34385;&#20102;&#36895;&#29575;&#38480;&#21046;&#12290;&#22914;&#26524;&#36229;&#36807;&#20102;&#38480;&#21046;&#65292;&#23427;&#36820;&#22238;HTTP&#29366;&#24577;&#30721;429&#65292;&#34920;&#31034;&#22826;&#22810;&#20010;&#35831;&#27714;&#12290;<\/p><h2>&#22788;&#29702;&#29575;&#38480;&#21046;&#20449;&#24687;&#12290;<\/h2><p>&#36890;&#30693;&#23458;&#25143;&#24403;&#21069;&#30340;&#36895;&#29575;&#38480;&#21046;&#29366;&#24577;&#20063;&#24456;&#37325;&#35201;&#12290;&#21487;&#20197;&#28155;&#21152;&#21709;&#24212;&#22836;&#26469;&#23454;&#29616;&#36825;&#19968;&#28857;&#65306;<\/p><pre><code>\/\/ Add these headers inside the index() function before the return statement\n$response = new Response();\n$response-&gt;headers-&gt;set('X-RateLimit-Limit', $limiter-&gt;getLimit());\n$response-&gt;headers-&gt;set('X-RateLimit-Remaining', $limiter-&gt;getLimit() - $limiter-&gt;getReservoir());\n$response-&gt;headers-&gt;set('X-RateLimit-Reset', $limiter-&gt;getResetTime());\n<\/code><\/pre><p>&#27492;&#22806;&#65292;&#24212;&#35813;&#25552;&#20379;&#36866;&#24403;&#30340;&#24322;&#24120;&#22788;&#29702;&#20197;&#25552;&#39640;&#29992;&#25143;&#20307;&#39564;&#65306;<\/p><pre><code>\/\/ src\/EventListener\/RateLimitExceededListener.php\nnamespace AppEventListener;\n\nuse SymfonyComponentHttpKernelEventExceptionEvent;\nuse SymfonyComponentHttpKernelExceptionTooManyRequestsHttpException;\nuse SymfonyComponentHttpFoundationResponse;\n\nclass RateLimitExceededListener\n{\n    public function onKernelException(ExceptionEvent $event)\n    {\n        $exception = $event-&gt;getThrowable();\n        if ($exception instanceof TooManyRequestsHttpException) {\n            $response = new Response('You have made too many requests', Response::HTTP_TOO_MANY_REQUESTS);\n            $event-&gt;setResponse($response);\n        }\n    }\n}\n<\/code><\/pre><p>&#35831;&#35760;&#24471;&#37197;&#32622;&#36825;&#20010;&#30417;&#21548;&#22120;&#65306;<\/p><pre><code>\/\/ config\/services.yaml\nservices:\n    AppEventListenerRateLimitExceededListener:\n        tags:\n            - { name: kernel.event_listener, event: kernel.exception }\n<\/code><\/pre><p>&#30830;&#20445;&#21487;&#25193;&#23637;&#24615;&#65306;&#23545;&#20110;&#39640;&#27969;&#37327;&#24212;&#29992;&#65292;&#25512;&#33616;&#20351;&#29992;&#20998;&#24067;&#24335;&#23384;&#20648;&#31995;&#32479;&#22914;Redis&#26469;&#23384;&#20648;&#36895;&#29575;&#38480;&#21046;&#35745;&#25968;&#12290;<\/p><h2>&#27491;&#22312;&#27979;&#35797;&#36895;&#29575;&#38480;&#21046;&#22120;<\/h2><p>&#22312;&#23454;&#26045;&#21518;&#65292;&#20351;&#29992;&#24037;&#20855;&#22914;Postman&#25110;cURL&#23545;API&#36827;&#34892;&#27979;&#35797;&#65292;&#20197;&#30830;&#20445;&#36895;&#29575;&#38480;&#21046;&#22120;&#25353;&#39044;&#26399;&#24037;&#20316;&#12290;<\/p><h2>&#32467;&#35770;<\/h2><p>&#22312;&#24744;&#30340;Symfony&#24212;&#29992;&#31243;&#24207;&#20013;&#23454;&#26045;&#36895;&#29575;&#38480;&#21046;&#26159;&#19968;&#31181;&#20445;&#25252;&#26381;&#21153;&#24182;&#30830;&#20445;&#28040;&#36153;&#32773;&#20844;&#24179;&#20351;&#29992;&#30340;&#22909;&#26041;&#27861;&#12290;&#25353;&#29031;&#36825;&#20010;&#25351;&#21335;&#65292;&#21487;&#20197;&#24110;&#21161;&#24744;&#35774;&#32622;&#19968;&#20010;&#20840;&#38754;&#30340;&#36895;&#29575;&#38480;&#21046;&#31995;&#32479;&#12290;&#35831;&#22987;&#32456;&#26681;&#25454;&#24744;&#30340;&#20855;&#20307;&#29992;&#20363;&#21644;&#22522;&#30784;&#35774;&#26045;&#33021;&#21147;&#26469;&#35843;&#25972;&#38480;&#21046;&#23450;&#20041;&#12290;<\/p><p>&#27880;&#24847;&#65306;&#25552;&#20379;&#30340;&#20195;&#30721;&#29255;&#27573;&#21644;&#37197;&#32622;&#22522;&#20110;Symfony 5&#65292;&#22914;&#26524;&#20351;&#29992;&#30340;&#26159;&#19981;&#21516;&#29256;&#26412;&#65292;&#35831;&#31245;&#20316;&#35843;&#25972;&#12290;<\/p><p>&#20026;&#20102;&#28145;&#20837;&#20102;&#35299;&#36895;&#29575;&#38480;&#21046;&#21644;&#39640;&#32423;&#37197;&#32622;&#65292;&#24744;&#21487;&#20197;&#26597;&#30475;Symfony&#23448;&#26041;&#25991;&#26723;&#25110;&#20351;&#29992;&#20854;&#20182;&#25552;&#20379;&#22686;&#24378;&#21151;&#33021;&#30340;&#31038;&#21306;&#24211;&#12290;<\/p><p>&#20027;&#21160;&#23454;&#26045;&#21644;&#30417;&#25511;&#36895;&#29575;&#38480;&#21046;&#26159;&#19968;&#31181;&#26368;&#20339;&#23454;&#36341;&#65292;&#23427;&#23558;&#26377;&#21161;&#20110;&#24744;&#30340;&#24212;&#29992;&#38543;&#30528;&#35268;&#27169;&#30340;&#22686;&#38271;&#32780;&#34920;&#29616;&#33391;&#22909;&#12290;&#24841;&#24555;&#32534;&#31243;&#65281;<\/p><\/body>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div><div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--3\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/xygcfznnzczhsdmwydzhsmzzzmddnq-400x300.jpg\" alt=\"&#38271;&#24037;&#30721;&#22900;1523\" class=\"wp-image-2906\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">&#38271;&#24037;&#30721;&#22900;1523<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<p>&#22312; Symfony &#20013;&#23454;&#29616;&#38480;&#27969;&#26159;&#19968;&#31181;&#25511;&#21046;&#35775;&#38382;&#36895;&#29575;&#30340;&#26377;&#25928;&#26041;&#27861;&#12290;&#23427;&#21487;&#20197;&#24110;&#21161;&#36991;&#20813;&#22240;&#22823;&#37327;&#35831;&#27714;&#21516;&#26102;&#21040;&#36798;&#26381;&#21153;&#22120;&#32780;&#23548;&#33268;&#30340;&#24615;&#33021;&#38382;&#39064;&#65292;&#24182;&#20445;&#25252;&#24212;&#29992;&#31243;&#24207;&#20813;&#21463;&#36807;&#36733;&#25915;&#20987;&#12290;<\/p>\n<h3>&#20160;&#20040;&#26159;&#38480;&#27969;&#65311;<\/h3>\n<p>&#38480;&#27969;&#26159;&#19968;&#31181;&#38480;&#21046;&#31995;&#32479;&#36164;&#28304;&#65288;&#22914; CPU &#36164;&#28304;&#12289;&#20869;&#23384;&#31561;&#65289;&#20351;&#29992;&#30340;&#25216;&#26415;&#65292;&#26088;&#22312;&#38450;&#27490;&#31995;&#32479;&#36164;&#28304;&#34987;&#36807;&#24230;&#28040;&#32791;&#65292;&#20174;&#32780;&#25552;&#39640;&#31995;&#32479;&#30340;&#31283;&#23450;&#24615;&#19982;&#23433;&#20840;&#24615;&#12290;<\/p>\n<h3>&#23454;&#29616;&#38480;&#27969;&#30340;&#26041;&#27861;<\/h3>\n<ol>\n<li>\n<p><strong>&#32531;&#23384;&#20196;&#29260;<\/strong>&#65306;<\/p>\n<ul>\n<li>&#20351;&#29992; Redis &#25110; Memcached &#31561;&#32531;&#23384;&#26381;&#21153;&#26469;&#23384;&#20648;&#20196;&#29260;&#12290;<\/li>\n<li>&#24403;&#29992;&#25143;&#23581;&#35797;&#33719;&#21462;&#25968;&#25454;&#26102;&#65292;&#20808;&#20174;&#32531;&#23384;&#20013;&#26816;&#26597;&#26159;&#21542;&#26377;&#21487;&#29992;&#30340;&#20196;&#29260;&#12290;<\/li>\n<li>&#22914;&#26524;&#26377;&#20196;&#29260;&#65292;&#21017;&#20351;&#29992;&#20196;&#29260;&#39564;&#35777;&#29992;&#25143;&#30340;&#35831;&#27714;&#26159;&#21542;&#31526;&#21512;&#38480;&#27969;&#35268;&#21017;&#12290;<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>&#26102;&#38388;&#25139;<\/strong>&#65306;<\/p>\n<ul>\n<li>&#35774;&#32622;&#19968;&#20010;&#26102;&#38388;&#31383;&#21475;&#65288;&#20363;&#22914; 5 &#20998;&#38047;&#65289;&#65292;&#22312;&#27492;&#26102;&#38388;&#20869;&#19981;&#20801;&#35768;&#22810;&#20010;&#35831;&#27714;&#21516;&#26102;&#21457;&#36215;&#12290;<\/li>\n<li>&#29992;&#25143;&#27599;&#27425;&#35831;&#27714;&#37117;&#38656;&#35201;&#28155;&#21152;&#19968;&#20010;&#26102;&#38388;&#25139;&#21040;&#35831;&#27714;&#22836;&#20013;&#12290;<\/li>\n<li>&#26381;&#21153;&#22120;&#31471;&#26816;&#26597;&#27599;&#20010;&#35831;&#27714;&#30340;&#26102;&#38388;&#25139;&#65292;&#22914;&#26524;&#36229;&#36807;&#26102;&#38388;&#31383;&#21475;&#65292;&#21017;&#25298;&#32477;&#35813;&#35831;&#27714;&#12290;<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>API &#26657;&#39564;<\/strong>&#65306;<\/p>\n<ul>\n<li>&#23545; API &#35831;&#27714;&#36827;&#34892;&#26657;&#39564;&#65292;&#30830;&#20445;&#20854;&#31526;&#21512;&#29305;&#23450;&#35268;&#21017;&#12290;<\/li>\n<li>&#22914;&#26524;&#19981;&#31526;&#21512;&#35268;&#21017;&#65292;&#21487;&#20197;&#35774;&#32622;&#30456;&#24212;&#30340;&#38169;&#35823;&#30721;&#21644;&#25552;&#31034;&#20449;&#24687;&#12290;<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>&#31034;&#20363;&#20195;&#30721;&#65306;<\/h3>\n<pre><code class=\"language-php\">use SensioBundleFrameworkExtraBundleConfigurationIsGranted;\nuse SymfonyComponentHttpFoundationRequest;\n\nclass MyController\n{\n    public function indexAction(Request $request)\n    {\n        \/\/ &#26816;&#26597;&#35831;&#27714;&#26159;&#21542;&#31526;&#21512;&#38480;&#27969;&#35268;&#21017;\n        if ($this-&gt;isRequestRateLimited($request)) {\n            throw new AccessDeniedException('Too many requests');\n        }\n\n        \/\/ &#20854;&#20182;&#25805;&#20316;\n        return new Response();\n    }\n\n    private function isRequestRateLimited(Request $request): bool\n    {\n        $timestamp = $request-&gt;headers-&gt;get('X-My-Timestamp');\n\n        if (!$timestamp) {\n            return false; \/\/ &#35831;&#27714;&#27809;&#26377;&#25351;&#23450;&#26102;&#38388;&#25139;\n        }\n\n        $lastTimestamp = strtotime('-' . $this-&gt;getTimeWindow() . ' seconds'); \/\/ &#20551;&#35774;&#31383;&#21475;&#20026;5&#20998;&#38047;\n\n        return strtotime($timestamp) &lt; $lastTimestamp;\n    }\n\n    protected function getTimeWindow(): int\n    {\n        \/\/ &#20320;&#21487;&#20197;&#26681;&#25454;&#38656;&#35201;&#35843;&#25972;&#36825;&#20010;&#20540;\n        return 60 * 5; \/\/ 5&#20998;&#38047;\n    }\n}<\/code><\/pre>\n<h3>&#27880;&#24847;&#20107;&#39033;<\/h3>\n<ul>\n<li><strong>&#26102;&#38388;&#21644;&#31383;&#21475;<\/strong>&#65306;&#20320;&#38656;&#35201;&#26681;&#25454;&#23454;&#38469;&#38656;&#27714;&#35843;&#25972;&#36825;&#20004;&#20010;&#21442;&#25968;&#12290;&#36739;&#22823;&#30340;&#31383;&#21475;&#20801;&#35768;&#26356;&#22810;&#30340;&#35831;&#27714;&#36827;&#20837;&#65292;&#20294;&#21487;&#33021;&#20250;&#23548;&#33268;&#26356;&#39057;&#32321;&#30340;&#22833;&#36133;&#35831;&#27714;&#12290;<\/li>\n<li><strong>&#32531;&#23384;<\/strong>&#65306;&#20351;&#29992;&#32531;&#23384;&#31574;&#30053;&#26159;&#20248;&#21270;&#38480;&#27969;&#30340;&#19968;&#20010;&#37325;&#35201;&#26041;&#38754;&#12290;&#21512;&#29702;&#22320;&#36873;&#25321;&#32531;&#23384;&#31574;&#30053;&#65288;&#22914; Redis &#32531;&#23384;&#65289;&#24182;&#23450;&#26399;&#28165;&#29702;&#32531;&#23384;&#21487;&#20197;&#24110;&#21161;&#20943;&#23569;&#32531;&#23384;&#21629;&#20013;&#29575;&#19979;&#38477;&#30340;&#38382;&#39064;&#12290;<\/li>\n<\/ul>\n<p>&#36890;&#36807;&#19978;&#36848;&#31034;&#20363;&#20195;&#30721;&#65292;&#20320;&#21487;&#20197;&#24320;&#22987;&#22312; Symfony &#24212;&#29992;&#31243;&#24207;&#20013;&#23454;&#26045;&#38480;&#27969;&#21151;&#33021;&#12290;&#35831;&#27880;&#24847;&#65292;&#36825;&#21482;&#26159;&#19968;&#20010;&#22522;&#26412;&#26694;&#26550;&#65292;&#20855;&#20307;&#30340;&#23454;&#29616;&#23558;&#21462;&#20915;&#20110;&#20320;&#30340;&#20855;&#20307;&#19994;&#21153;&#38656;&#27714;&#21644;&#25216;&#26415;&#26632;&#12290;<\/p>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Bug&#32534;&#35793;&#29422; &#22312; Symfony &#20013;&#23454;&#29616;&#38480;&#27969;&#65288;Rate Limiting&#65289;&#21487;&#20197;&#36890;&#36807;&#22810;&#038;#3118..<\/p>\n","protected":false},"author":1,"featured_media":0,"menu_order":0,"template":"","meta":{"_acf_changed":false},"tags":[],"my1js2nav":[45],"tuisongtax":[],"class_list":["post-1095","my1js","type-my1js","status-publish","hentry","my1js2nav-symfony"],"acf":{"qian_art_seotitle":"","qian_art_seotitle_source":{"label":"SEO\u6807\u9898","type":"text","formatted_value":""},"qian_art_seokws":"","qian_art_seokws_source":{"label":"SEO\u5173\u952e\u8bcd","type":"text","formatted_value":""},"qian_art_stzhong":"","qian_art_stzhong_source":{"label":"\u4e2d | \u77ed\u6807\u9898","type":"text","formatted_value":""}},"_links":{"self":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js\/1095","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js"}],"about":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/types\/my1js"}],"author":[{"embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/users\/1"}],"wp:attachment":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/media?parent=1095"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/tags?post=1095"},{"taxonomy":"my1js2nav","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js2nav?post=1095"},{"taxonomy":"tuisongtax","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/tuisongtax?post=1095"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}