Skip to content

Commit

Permalink
rl
Browse files Browse the repository at this point in the history
  • Loading branch information
youfanx committed Apr 19, 2024
1 parent bf895eb commit 8091c30
Show file tree
Hide file tree
Showing 23 changed files with 2,291 additions and 22 deletions.
35 changes: 30 additions & 5 deletions rxlib-x/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
<HikariCP.version>4.0.3</HikariCP.version>
<druid.version>1.2.21</druid.version>
<redisson.version>3.27.2</redisson.version>
<guava.version>32.1.1-jre</guava.version>

<javaxMail.version>1.6.2</javaxMail.version>
<poi.version>5.2.2</poi.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -65,10 +69,31 @@
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.google.guava</groupId>-->
<!-- <artifactId>guava</artifactId>-->
<!-- <version>32.1.1-jre</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- pinyin-->
<dependency>
<groupId>org.ahocorasick</groupId>
<artifactId>ahocorasick</artifactId>
<version>0.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>${javaxMail.version}</version>
</dependency>
</dependencies>
</project>
2 changes: 1 addition & 1 deletion rxlib-x/src/main/java/org/rx/crawler/RemoteBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.rx.bean.FlagsEnum;
import org.rx.spring.MiddlewareConfig;
import org.rx.core.Linq;
import org.rx.core.Reflects;
import org.rx.exception.InvalidException;
import org.rx.net.Sockets;
import org.rx.net.rpc.Remoting;
import org.rx.net.rpc.RpcClientConfig;
import org.rx.spring.MiddlewareConfig;
import org.rx.spring.SpringContext;
import org.rx.util.function.*;

Expand Down
3 changes: 2 additions & 1 deletion rxlib-x/src/main/java/org/rx/jdbc/JdbcExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
import java.util.List;

import static org.rx.core.Extends.*;
import static org.rx.core.Sys.*;
import static org.rx.core.Sys.proxy;
import static org.rx.core.Sys.toJsonString;

@Slf4j
public class JdbcExecutor extends Disposable implements EventPublisher<JdbcExecutor>, JdbcExecutable {
Expand Down
5 changes: 5 additions & 0 deletions rxlib-x/src/main/java/org/rx/redis/RateLimiterAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.rx.redis;

public interface RateLimiterAdapter {
boolean tryAcquire();
}
9 changes: 7 additions & 2 deletions rxlib-x/src/main/java/org/rx/redis/RedisCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
import org.redisson.config.Config;
import org.rx.bean.BiTuple;
import org.rx.codec.CodecUtil;
import org.rx.core.*;
import org.rx.core.Cache;
import org.rx.core.CachePolicy;
import org.rx.core.RxConfig;
import org.rx.core.Tasks;
import org.rx.util.function.BiFunc;

import java.util.*;
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static org.rx.core.Extends.quietly;
Expand Down
55 changes: 55 additions & 0 deletions rxlib-x/src/main/java/org/rx/redis/RedisRateLimiter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.rx.redis;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateLimiterConfig;
import org.redisson.api.RateType;
import org.rx.core.Constants;

@Slf4j
public class RedisRateLimiter implements RateLimiterAdapter {
final RedisCache<?, ?> rCache;
final RRateLimiter limiter;

public int getPermitsPerSecond() {
return limiter.getConfig().getRate().intValue();
}

@Override
public boolean tryAcquire() {
return limiter.tryAcquire();
}

public RedisRateLimiter(@NonNull RedisCache<?, ?> rCache, String acquireKey) {
this(rCache, acquireKey, Constants.CPU_THREADS);
}

public RedisRateLimiter(@NonNull RedisCache<?, ?> rCache, String acquireKey, int permitsPerSecond) {
this.rCache = rCache;
limiter = createLimiter(acquireKey, permitsPerSecond, 1);
}

RRateLimiter createLimiter(String key, long rate, long rateInterval) {
RRateLimiter limiter = rCache.getClient().getRateLimiter(key);
if (limiter.isExists()) {
RateLimiterConfig config = limiter.getConfig();
if (config.getRate() == rate && config.getRateInterval() == RateIntervalUnit.SECONDS.toMillis(rateInterval)) {
return limiter;
}
}

log.info("trySetRate start, {} {}", key, rate);
int retry = 4;
// 循环直到重新配置成功
while (--retry > 0 && !limiter.trySetRate(RateType.OVERALL, rate, rateInterval, RateIntervalUnit.SECONDS)) {
limiter.delete();
limiter = rCache.getClient().getRateLimiter(key);
}
if (retry == 0) {
log.warn("trySetRate fail, {} {}", key, rate);
}
return limiter;
}
}
14 changes: 10 additions & 4 deletions rxlib-x/src/main/java/org/rx/redis/RedisUtil.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.rx.redis;

import lombok.RequiredArgsConstructor;
import com.google.common.util.concurrent.RateLimiter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.rx.core.Cache;
import org.rx.core.Strings;
import org.rx.core.Sys;
Expand All @@ -22,7 +21,14 @@ public static Lock wrapLock(RLock rLock) {
});
}

public static <TK, TV> Cache<TK, TV> wrapCache(String redisUrl) {
return Sys.fallbackProxy(Cache.class, new RedisCache<>(redisUrl), new Lazy<>(() -> Cache.getInstance(MemoryCache.class)));
public static <TK, TV> Cache<TK, TV> wrapCache(RedisCache<TK, TV> rCache) {
return Sys.fallbackProxy(Cache.class, rCache, new Lazy<>(() -> Cache.getInstance(MemoryCache.class)));
}

public static RateLimiterAdapter wrapRateLimiter(RedisRateLimiter rRateLimiter) {
return Sys.fallbackProxy(RateLimiterAdapter.class, rRateLimiter, new Lazy<>(() -> {
RateLimiter limiter = RateLimiter.create(rRateLimiter.getPermitsPerSecond());
return () -> limiter.tryAcquire();
}));
}
}
37 changes: 30 additions & 7 deletions rxlib-x/src/main/java/org/rx/spring/BeanRegister.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
package org.rx.spring;

import lombok.extern.slf4j.Slf4j;
import org.rx.core.Cache;
import org.rx.core.IOC;
import org.rx.core.Strings;
import org.rx.core.*;
import org.rx.exception.InvalidException;
import org.rx.redis.RateLimiterAdapter;
import org.rx.redis.RedisCache;
import org.rx.redis.RedisRateLimiter;
import org.rx.redis.RedisUtil;
import org.rx.util.Servlets;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static org.rx.core.Extends.ifNull;

@Configuration
@Slf4j
public class BeanRegister {
public static final String REDIS_PROP_NAME = "app.redisUrl";

@Bean
@ConditionalOnProperty(name = REDIS_PROP_NAME)
public <TK, TV> Cache<TK, TV> redisCache(MiddlewareConfig redisConfig) {
if (Strings.isEmpty(redisConfig.getRedisUrl())) {
public <TK, TV> RedisCache<TK, TV> redisCache(MiddlewareConfig conf) {
if (Strings.isEmpty(conf.getRedisUrl())) {
throw new InvalidException("app.redisUrl is null");
}

Cache<TK, TV> cache = RedisUtil.wrapCache(redisConfig.getRedisUrl());
IOC.register(Cache.class, cache);
RedisCache<TK, TV> cache = new RedisCache<>(conf.getRedisUrl());
IOC.register(Cache.class, RedisUtil.wrapCache(cache));
log.info("register RedisCache ok");
return cache;
}

@Bean
@ConditionalOnProperty(name = REDIS_PROP_NAME)
public RateLimiterAdapter httpRateLimiterAdapter(RedisCache<?, ?> rCache, MiddlewareConfig conf) {
String[] acquireWhiteList = conf.getLimiterWhiteList();
return () -> {
String clientIp = ifNull(Servlets.requestIp(), "ALL");

if (!Arrays.isEmpty(acquireWhiteList)
&& Linq.from(acquireWhiteList).any(p -> Strings.startsWith(clientIp, p))) {
return true;
}

String rk = "RateLimiter:" + clientIp;
RateLimiterAdapter adapter = IOC.<String, RateLimiterAdapter>weakMap(false)
.computeIfAbsent(rk, k -> RedisUtil.wrapRateLimiter(new RedisRateLimiter(rCache, k, conf.getLimiterPermits())));
return adapter.tryAcquire();
};
}
}
3 changes: 1 addition & 2 deletions rxlib-x/src/main/java/org/rx/spring/MiddlewareConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Data
Expand All @@ -13,6 +11,7 @@
public class MiddlewareConfig {
private String redisUrl;
private String storeUrl;

private int limiterPermits = 12;
private String limiterWhiteList;

Expand Down
Loading

0 comments on commit 8091c30

Please sign in to comment.