현재 제한 요구 사항은 동시 실행 수를 제한하는 것입니다. 이 수를 초과하면 대기열에 캐시되어야 합니다. 이번 글은 주로 Koa 서비스의 전류 제한 방식에 대해 소개하고 있는데, 편집자는 이것이 꽤 좋다고 생각합니다. 이제 여러분께 공유하고 참고하겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.
최근에 요청을 받았습니다. 서버를 설정하고 요청을 받을 때 제공된 인터페이스를 호출한 다음 결과를 반환하면 됩니다. 이 인터페이스의 성능 문제로 인해 동시에 요청 수는 특정 수를 초과할 수 없으며 서비스에서 전류가 제한되어야 합니다.
koa 미들웨어는 next를 호출하지 않습니다
원래 아이디어는 koa 미들웨어에서 계산하고 6개 이상이면 다음 함수를 캐시하는 것입니다. 진행 중인 작업이 끝나면 next를 호출하여 다른 요청을 계속하세요.
나중에 koa 미들웨어에서는 다음 함수 요청이 실행되지 않으면 중지되지 않고 대신 후속 미들웨어가 더 이상 호출되지 않고 콘텐츠가 직접 반환된다는 것을 발견했습니다.
const Koa = require('koa'); const app = new Koa(); app.use((ctx, next) => { console.log('middleware 1'); setTimeout(() => { next(); }, 3000); ctx.body = 'hello'; }); app.use((ctx, next) => { console.log('middleware 2'); }); app.listen(8989);
위 코드는 먼저 콘솔에 '미들웨어 1'을 인쇄합니다 => 브라우저가 'hello'를 수신합니다 => 콘솔이 '미들웨어 2'를 인쇄합니다.
여기서 주목해야 할 또 다른 점은 요청이 종료된 후에도 다음 메서드를 계속 호출할 수 있으며 후속 미들웨어가 계속 실행된다는 것입니다(그러나 요청이 반환되었기 때문에 ctx에 대한 수정 사항은 적용되지 않습니다). ). 마찬가지로 닫기 요청(close)도 동일한 방식으로 작동합니다.
Await를 사용하여 요청을 기다리게 만듭니다.
다음 함수의 실행을 지연시키는 것은 목적을 달성할 수 없습니다. 다음으로 생각해야 할 자연스러운 일은 현재 요청을 기다리는 데 wait를 사용하는 것입니다. Wait 함수는 Promise를 반환합니다. 이 Promise에 해결 함수를 대기열에 저장하고 호출을 지연합니다.
const Koa = require('koa'); const app = new Koa(); const queue = []; app.use(async (ctx, next) => { setTimeout(() => { queue.shift()(); }, 3000); await delay(); ctx.body = 'hello'; }); function delay() { return new Promise((resolve, reject) => { queue.push(resolve); }); } app.listen(8989);
위 코드는 지연 함수에서 Promise를 반환하고 Promise의 해결 함수가 대기열에 저장됩니다. 요청이 계속해서 실행될 수 있도록 3초 후에 대기열의 해결 기능이 실행되도록 타이머를 설정합니다.
라우팅이나 요청에 대한 흐름이 제한되나요?
전류 제한의 기본 원리를 구현한 후 다음 질문은 전류 제한 코드를 어디에 작성해야 합니까? 기본적으로 두 가지 입장이 있습니다.
인터페이스에 대한 전류 제한
우리의 요구로 인해 전류 제한은 요청된 인터페이스의 제한된 성능으로 인해 발생합니다. 따라서 이 요청의 흐름을 별도로 제한할 수 있습니다.
async function requestSomeApi() { // 如果已经超过了最大并发 if (counter > maxAllowedRequest) { await delay(); } counter++; const result = await request('http://some.api'); counter--; queue.shift()(); return result; }
아래에는 편리한 재사용 가능 버전도 있습니다.
async function limitWrapper(func, maxAllowedRequest) { const queue = []; const counter = 0; return async function () { if (counter > maxAllowedRequest) { await new Promise((resolve, reject) => { queue.push(resolve); }); } counter++; const result = await func(); counter--; queue.shift()(); return result; } }
경로에 대한 전류 제한
이 방법은 koa 미들웨어를 작성하고 미들웨어의 전류를 제한하는 것입니다.
async function limiter(ctx, next) => { // 如果超过了最大并发数目 if (counter >= maxAllowedRequest) { // 如果当前队列中已经过长 await new Promise((resolve, reject) => { queue.push(resolve); }); } store.counter++; await next(); store.counter--; queue.shift()(); };
그런 다음 다른 경로에 대해 라우터에서 이 미들웨어를 사용하세요.
router.use('/api', rateLimiter);
비교
인터페이스에 대해 전류 제한을 구현했습니다. 로직이 약간 혼란스럽다고 생각하여 라우팅에 대해 전류 제한으로 전환했습니다.
다른 요청을 받을 때까지 저는 이 인터페이스를 세 번 요청하고 세 요청의 결과 배열을 반환하고 싶었습니다. 이제 문제가 발생합니다. 전류가 제한되어 있기 때문에 인터페이스를 직접 호출할 수 없습니다. 현재 제한은 라우팅을 기반으로 하기 때문에 요청 인터페이스의 기능을 직접 호출할 수 없습니다. 무엇을 해야 할까요? 이 경로를 요청하고 직접 요청할 수만 있습니다. . .
주의사항
close 이벤트를 듣고 대기열에서 요청을 제거합니다.
대기열에 저장된 요청은 사용자에 의해 취소될 수 있습니다. 앞에서 언급했듯이 koa에서는 요청이 취소되더라도 후속 미들웨어는 계속 실행되므로 전류 제한이 필요한 인터페이스도 실행되므로 낭비가 발생합니다.
이 목적을 달성하려면 닫기 이벤트를 들을 수 있습니다. 각 요청을 해시 값으로 표시해야 합니다.
ctx.res.on('close', () => { const index = queue.findIndex(item => item.hash === hash); if (index > -1) { queue.splice(index, 1); } });
시간 초과 설정
사용자가 너무 오래 기다리는 것을 방지하려면 koa에서는 쉬운 타임아웃 구현:
const server = app.listen(config.port); server.timeout = DEFAULT_TIMEOUT;
현재 대기열이 너무 깁니다
현재 대기열이 너무 길면 대기열에 참여하더라도 시간 초과됩니다. 따라서 대기열이 너무 긴 상황도 처리해야 합니다.
if (queue.length > maxAllowedRequest) { ctx.body = 'error message'; return; }
관련 권장 사항:
The Road of Java Architect - 전류 제한 기술 및 다양한 프로그래밍 언어
위 내용은 Koa 서비스 전류 제한 방법 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!