java网关限流_基于Zuul网关Filter的分布式限流

zuul-redislimiter-spring-boot

rate limiter for zuul

Quickstart

Clone, build and install

git clone https://github.com/tangaiyun/zuul-redislimiter-spring-boot.git

cd zuulredislimiter/zuul-redislimiter-spring-boot-starter

mvn clean install

Add to your POM

Then create a zuul proxy project refer to sample project "zuulredislimiter/zuulapp",and you need to add dependency in pom.xml

package com.tay.zuulapp;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication

@EnableZuulProxy

public class ZuulappApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulappApplication.class, args);

}

}

org.springframework.cloud

spring-cloud-starter-netflix-zuul

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

org.springframework.boot

spring-boot-starter-test

test

com.tay

zuul-redislimiter-spring-boot-starter

0.0.1-SNAPSHOT

Configuration

For resources/application.yml you need to add the following lines.

server:

port: 8000

spring:

application:

name: service-zuul

zuul:

routes:

service1: /s1/**

service2: /s2/**

redis-limiter:

redis-host: 127.0.0.1#Redis server host

policy-map:

api-a: #limiting policy with serviceId api-a

order: -1 #n policies matched, which with lower order value has high priority

baseExp: Headers['userid']#base on HTTP header with key "userid"

pathRegExp: /s1/.*#URI pattern

timeUnit: MINUTES#timeUnit, supports SECONDS,MINUTES,HOURS,DAYS

permits: 2 #Number of visits allowed per a timeUnit

api-a1:

order: 0

baseExp: Cookies['userid']

pathRegExp: /s1.*

timeUnit: MINUTES

permits: 3

api-b:

order: 2

baseExp: Headers['userid']

pathRegExp: /s2/.*

timeUnit: MINUTES

permits: 5

eureka:

client:

serviceUrl:

defaultZone: http://localhost:8761/eureka/

instance:

prefer-ip-address: true

Create a sample microservice refer to zuulredislimiter/service1

package com.tay.service1;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping("/demo1")

public class Controller1 {

@GetMapping("/test11")

public String test1() {

return "test11!";

}

@GetMapping("/test12")

public String test2() {

return "test12!";

}

}

server:

port: 8001

spring:

application:

name: service1

eureka:

client:

serviceUrl:

defaultZone: http://localhost:8761/eureka/

instance:

prefer-ip-address: true

Create another sample microservice like zuulredislimiter/service2

package com.tay.service2;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping("/demo2")

public class Controller2 {

@GetMapping("/test21")

public String test1() {

return "test21!";

}

@GetMapping("/test22")

public String test2() {

return "test22!";

}

}

server:

port: 8002

spring:

application:

name: service2

eureka:

client:

serviceUrl:

defaultZone: http://localhost:8761/eureka/

instance:

prefer-ip-address: true

Create an Eureka server project like zuulredislimiter/eurekaserver

package com.tay.eurekaserver;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer

@SpringBootApplication

public class EurekaserverApplication {

public static void main(String[] args) {

SpringApplication.run(EurekaserverApplication.class, args);

}

}

server:

port: 8761

eureka:

client:

register-with-eureka: false

fetch-registry: false

Start Redis server

Start Redis server on a local machine or with Docker.

sudo docker run -d -p 6379:6379 redis

start eurekaserver project

start zuulapp project

start service1 project

start service2 project

Testing

You can use a HTTP client tool such as Postman, restd or curl, and get the URL http://localhost:8000/s2/demo2/test21. Don't forget to add a pair value userid=tom in your HTTP request header. You will be able to find the user with userid "tom" can visit this url five times successfully at most in one minute.

Advanced Guide

Complete Configuration Items

spring:

redis-limiter:

redis-host: 127.0.0.1# redis server IP default:127.0.0.1

redis-port: 6379 # redis service port default:6379

redis-password: test# redis password default:null

redis-connection-timeout: 2000 # redis connection timeout default:2000

redis-pool-max-idle: 50 # redis pool max idle default: 50

redis-pool-min-idle: 10 # redis pool mim idle default:10

redis-pool-max-wait-millis: -1# max wait time for get connection default:-1

redis-pool-max-total: 200 # max total connection default:200

redis-key-prefix: #RL # key prefix for visit footprint default: #RL

check-action-timeout: 100 # check action execution timeout default: 100

channel:#RLConfigChannel # conf change event pub/sub channel default: #RLConfigChannel

policy-map: # rate limiting policies

api-a: # unique service id

order: -1 # order

baseExp: Headers['userid']# value to base on, Spel expression without "#", supports Headers['xxx'] or Cookies['xxx']

pathRegExp: /s1/.*# URI path pattern, a Regular expression

timeUnit: MINUTES# timeUnit supports SECONDS, MINUTES, HOURS,DAYS

permits: 2 # Number of visits allowed per a timeUnit

api-a1:

order: 0

baseExp: Headers['userid']

pathRegExp: /s1.*

timeUnit: MINUTES

permits: 3

...

Dynamic configuration

We can change the limiting policy by internal RESTful API.

@RequestMapping("/zuullimiterpolicy")

public class LimitingPolicyResource {

...

@PostMapping

public void add(@RequestBody LimitingPolicy limitingPolicy, HttpServletResponse response) throws IOException{

...

}

@PutMapping

public void update(@RequestBody LimitingPolicy limitingPolicy, HttpServletResponse response) throws IOException {

...

}

@GetMapping("/{serviceId}")

public LimitingPolicy get(@PathVariable("serviceId") String serviceId) {

...

}

@DeleteMapping("/{serviceId}")

public void delete(@PathVariable("serviceId") String serviceId) {

...

}

Currently, this framework support four actions (add, update, query, delete).

For example (as in the zuulapp project)

{

"serviceId": "api-a",

"order": -1,

"baseExp": "Headers['userid']",

"pathRegExp": "/s1/.*",

"timeUnit": "MINUTES",

"permits": 2,

"delete": false

}

If we want to update configuration, assign Content-Type as application/json, then excute PUT http://localhost:8000/zuullimiterpolicy, the request body as below:

{

"serviceId": "api-a",

"order": -1,

"baseExp": "Headers['userid']",

"pathRegExp": "/s1/.*",

"timeUnit": "MINUTES",

"permits": 10,

"delete": false

}

then the limiting policy for service with serviceId "api-a" changed.

If we want to delete a limiting policy with serviceId "api-b", execute DELETE http://localhost:8000/zuullimiterpolicy/api-b, the limiting policy with serviceId "api-b" will be deleted.

add a new limiting policy, assign Content-Type as application/json, then excute POST http://localhost:8000/zuullimiterpolicy, the request body as below:

{

"serviceId": "api-d",

"order": -1,

"baseExp": "Headers['userid']",

"pathRegExp": "/s3/.*",

"timeUnit": "MINUTES",

"permits": 10,

"delete": false

}

please be careful, the serviceId and pathRegExp should not be conflict with existed limiting policy.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值