package demo ; import com.google.common.util.concurrent.RateLimiter; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @EnableCircuitBreaker @EnableFeignClients @EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class GreetingsClientApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(GreetingsClientApplication.class, args); } } @FeignClient("greetings-service") interface GreetingsClient { @RequestMapping(method = RequestMethod.GET, value = "/greetings/{name}") Greeting greet(@PathVariable("name") String name); } @RestController class GreetingsApiGatewayRestController { private final GreetingsClient greetingsClient; @Autowired public GreetingsApiGatewayRestController(GreetingsClient client) { this.greetingsClient = client; } public String fallback(String name) { return "ohai!"; } @HystrixCommand(fallbackMethod = "fallback") @RequestMapping(method = RequestMethod.GET, value = "/hi/{name}") String greet(@PathVariable String name) { return this.greetingsClient.greet(name).getGreeting(); } } class Greeting { private String greeting; public String getGreeting() { return greeting; } } //@Component class RateLimitingZuulFilter extends ZuulFilter { private final RateLimiter rateLimiter = RateLimiter.create(1.0 / 30.0); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return Ordered.HIGHEST_PRECEDENCE + 100; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { try { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletResponse response = currentContext.getResponse(); if (!this.rateLimiter.tryAcquire()) { response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); response.getWriter().append(HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase()); currentContext.setSendZuulResponse(false); } } catch (IOException e) { ReflectionUtils.rethrowRuntimeException(e); } return null; } }