흐름 제한 실현 및 해결 방안
9995 단어 JAVA 개발
,
,
,
, kafka
,
등 기술 차원: 1. 같은 요청이 있는지 판단하기 위해 자신의 캐시를 통해 같은 요청을 막을 수 있다. 2, 부하 균형, 예를 들어nginx3,캐시 데이터베이스로 핫이슈 데이터 get을 캐시에 저장합니다. redis, ES4, 연결 탱크 업무 차원을 잘 사용합니다. 1. 상호작용을 추가하고 줄을 서서 기다립니다
com.google.guava
guava
23.0
package com.citydo.dialogue.controller;
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
@RestController
public class HomeController {
// 1 10
private RateLimiter limiter = RateLimiter.create(10.0);
//RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit);
//RateLimiter limiter = RateLimiter.create(5, 1000, TimeUnit.MILLISECONDS);
//permitsPerSecond:
// warmupPeriod:
@GetMapping("/test/{name}")
public String Test(@PathVariable("name") String name){
// RateLimiter, permits
final double acquire = limiter.acquire();
System.out.println("--------"+acquire);
// double 0
if(acquire>=(-1e-6)&&acquire<=(1e-6)){
return name;
}else{
return " ";
}
}
}
이것은 약간 QPS 데이터 제어와 유사하다. QPS가 특정한 한도값을 초과할 때 데이터 제어를 하는 조치를 취한다.직접 거부: 방식은 기본 데이터 제어 방식입니다. QPS가 임의의 규칙의 한도값을 초과하면 새로운 요청은 즉시 거부됩니다. 거부 방식은 Exception을 던지거나 404를 되돌려줍니다.이런 방식은 시스템 처리 능력에 대해 확실하게 알고 있는 상황에서 예를 들어 압력 측정을 통해 시스템의 정확한 수위를 확정했을 때 적용된다.
방법 2. redis 증가 1을 한 번 요청하면 키는
sentinel: 、Warm Up、
또는 하나IP+
일 수 있습니다. 없으면 만들 수 있습니다. 만료 시간 설정 차단기를 설정해야 합니다.package com.citydo.dialogue.config;
import com.citydo.dialogue.service.AccessLimitInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
*
* @author nick
*/
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//addPathPatterns
registry.addInterceptor(new AccessLimitInterceptor())
//
.addPathPatterns("/**");
//swagger2 .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
//.excludePathPatterns("/*")
//
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/");
}
}
차단 방법
package com.citydo.dialogue.service;
import com.citydo.dialogue.entity.AccessLimit;
import com.citydo.dialogue.utils.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
public class AccessLimitInterceptor implements HandlerInterceptor {
// RedisTemplate redis
@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
if (!method.isAnnotationPresent(AccessLimit.class)) {
return true;
}
AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);
if (accessLimit == null) {
return true;
}
int limit = accessLimit.limit();
int sec = accessLimit.sec();
String key = IpUtil.getIpAddr(request) + request.getRequestURI();
//
String formatDate=new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
//String key="request_"+formatDate;
Integer maxLimit = redisTemplate.opsForValue().get(key);
if (maxLimit == null) {
//set
redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS);
} else if (maxLimit < limit) {
redisTemplate.opsForValue().set(key, maxLimit + 1, sec, TimeUnit.SECONDS);
} else {
output(response, " !");
return false;
}
}
return true;
}
public void output(HttpServletResponse response, String msg) throws IOException {
response.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(msg.getBytes("UTF-8"));
} catch (IOException e) {
e.printStackTrace();
} finally {
outputStream.flush();
outputStream.close();
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
메모로 설정할 수도 있고 매개 변수를 직접 추가할 수도 있습니다
package com.citydo.dialogue.entity;
import java.lang.annotation.*;
@Inherited
@Documented
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
// sec
int limit() default 5;
//
int sec() default 5;
}
redis 구성 작성
package com.citydo.dialogue.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis
*
* @author nick
*/
@Configuration
public class RedisConfig {
/**
*
*/
@Bean
public RedisTemplate
방법 3. 분포식 유동 제한, 분포식 유동 제한의 가장 관건적인 것은 유동 제한 서비스를 원자화하는 것이다. 해결 방안은
+
또는 redis+lua
기술로 실현할 수 있다.방법 4. 연못화 기술을 사용하여 총 자원 수: 연결 연못, 스레드 연못을 제한할 수 있다.예를 들어 모든 응용 프로그램에 분배된 데이터베이스 연결이 100이라면 본 응용 프로그램은 최대 100개의 자원을 사용할 수 있으며 기다리거나 던질 수 있는 이상을 초과할 수 있다.
메서드 5. Tomcat을 사용한 경우 Connector의 구성에는 다음과 같은 몇 가지 매개변수가 있습니다.
maxThreads:
Tomcat , , 。
maxConnections:
, 。
acceptCount:
Tomcat , , , 。
메서드 6, Java의 AtomicLong을 사용하여 코드를 나타내는 인터페이스의 총 동시/요청 수를 제한합니다.
try{
if(atomic.incrementAndGet() > ) {
//
} else {
//
}
} finally {
atomic.decrementAndGet();
}
메서드 7, 어떤 인터페이스의 시간 창 요청 수를 Guava의 Cache로 제한하여 코드를 표시합니다.
LoadingCache counter = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(newCacheLoader() {
@Override
public AtomicLong load(Long seconds) throws Exception {
return newAtomicLong(0);
}
});
longlimit =1000;
while(true) {
//
long currentSeconds = System.currentTimeMillis() /1000;
if(counter.get(currentSeconds).incrementAndGet() > limit) {
System.out.println(" : " + currentSeconds);
continue;
}
//
}
어떤 목적이든 흐름을 제한하기 위해서다.참조:https://blog.csdn.net/fanrenxiang/article/details/80683378참조:https://mp.weixin.qq.com/s/2_oDGJiI1GhaNYnaeL7Qpg소스 코드:https://github.com/863473007/springboot_current_limiting
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
웹x 프레임워크 파일 업로드 저장 서버 분석 실현최근에는 Webx 프레임워크 구현을 배우기 시작했다.Webx 프레임워크에 대한 지식을 간단히 배웠습니다. csv 형식의 파일을 업로드하여 서버에 저장하고 파일 내의 데이터를 데이터베이스로 가져오는 기능을 개발했습니다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.