Skip to content

Commit

Permalink
Merge pull requests #197
Browse files Browse the repository at this point in the history
Instance-level circuit breaking, supporting smooth traffic recovery
  • Loading branch information
chenzhiguo authored Jan 6, 2025
2 parents 84a9118 + d0d60ef commit 59fc39c
Show file tree
Hide file tree
Showing 51 changed files with 1,428 additions and 705 deletions.
24 changes: 13 additions & 11 deletions RELEASE-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
3. 新增支持 Spring cloud 客户端获取到服务端的异常,便于重试和熔断
4. 新增支持 Spring cloud 端口路由
5. 新增支持 Redis 集群级限流
6. 完善扩展的条件匹配,支持自定义组合条件,简化了相关配置
7. 完善流控中的标签匹配逻辑
8. 性能优化
9. 提供上下文锁,便于拦截器使用
10. 修改配置,默认不启动多活、泳道和流控的治理,通过环境变量配置开启
11. 修复当在JAVA_TOOL_OPTIONS中配置Agent的时候,会影响Java运维工具使用的问题,支持配置过滤掉相关应用
12. 修复OpenJDK兼容问题
13. 修复和其它Agent冲突的问题,把Bootstrap打包在一起
14. 修复调用原始方法,也会触发OnExit/OnSuccess/OnError的拦截问题
15. 修复Sofarpc注入问题
16. 修复其它问题
6. 新增支持 W3c Baggage 透传
7. 新增支持实例级熔断的流量渐进性恢复
8. 完善扩展的条件匹配,支持自定义组合条件,简化了相关配置
9. 完善流控中的标签匹配逻辑
10. 性能优化
11. 提供上下文锁,便于拦截器使用
12. 修改配置,默认不启动多活、泳道和流控的治理,通过环境变量配置开启
13. 修复当在JAVA_TOOL_OPTIONS中配置Agent的时候,会影响Java运维工具使用的问题,支持配置过滤掉相关应用
14. 修复OpenJDK兼容问题
15. 修复和其它Agent冲突的问题,把Bootstrap打包在一起
16. 修复调用原始方法,也会触发OnExit/OnSuccess/OnError的拦截问题
17. 修复Sofarpc注入问题
18. 修复其它问题

## 1.5.2

Expand Down
24 changes: 13 additions & 11 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
3. Added support for Spring Cloud clients to retrieve exceptions from the server, facilitating retry and circuit breaking.
4. Added support for Spring Cloud port-based routing.
5. Added support for cluster-level rate limiting by Redis.
6. Improved extension condition matching, supporting custom combination conditions, and simplified related configurations
7. Improved label matching logic in flow control
8. Performance optimization
9. Provide context lock to facilitate the use of interceptors
10. Modified configuration, by default not starting multi-active, swimlane, and flow control governance, enabled through environment variable configuration
11. Fixed the issue that configuring Agent in JAVA_TOOL_OPTIONS would affect the use of Java operational tools, supporting configuration to filter out related applications
12. Fixed OpenJDK compatibility issues
13. Fixed issues with conflicts with other Agents, packaging Bootstrap together
14. Fixed the issue that calling the original method would also trigger OnExit/OnSuccess/OnError interceptors
15. Fixed Sofarpc injection problem
16. Fixed other issues
6. Added support for W3c Baggage transparent transmission.
7. Added support for gradual traffic recovery at the instance-level circuit breaking.
8. Improved extension condition matching, supporting custom combination conditions, and simplified related configurations
9. Improved label matching logic in flow control
10. Performance optimization
11. Provide context lock to facilitate the use of interceptors
12. Modified configuration, by default not starting multi-active, swimlane, and flow control governance, enabled through environment variable configuration
13. Fixed the issue that configuring Agent in JAVA_TOOL_OPTIONS would affect the use of Java operational tools, supporting configuration to filter out related applications
14. Fixed OpenJDK compatibility issues
15. Fixed issues with conflicts with other Agents, packaging Bootstrap together
16. Fixed the issue that calling the original method would also trigger OnExit/OnSuccess/OnError interceptors
17. Fixed Sofarpc injection problem
18. Fixed other issues

## 1.5.2

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.core.util;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
* Utility class for performing atomic operations on {@link AtomicReference}.
*/
public class AtomicUtils {

/**
* Atomically updates the value of the given {@link AtomicReference} if the current value satisfies the specified predicate.
* If the predicate is satisfied, the new value is set using {@link AtomicReference#compareAndSet(Object, Object)}.
* If the update is successful and a success consumer is provided, the consumer is called with the old and new values.
* If the update is successful, the new value is returned. Otherwise, the old value is returned.
*
* @param reference the {@link AtomicReference} to update
* @param value the new value to set
* @param predicate a predicate that tests the current value; if null, the update is always attempted
* @param success a consumer that is called with the old and new values if the update is successful; if null, no consumer is called
* @return the new value if the update was successful, otherwise the old value
*/
public static <V> V update(AtomicReference<V> reference, V value, Predicate<V> predicate, BiConsumer<V, V> success) {
V old;
while (true) {
old = reference.get();
if (predicate == null || predicate.test(old)) {
if (reference.compareAndSet(old, value)) {
if (success != null) {
success.accept(old, value);
}
return value;
}
} else {
return old;
}
}
}

/**
* Atomically gets or updates the value associated with the specified key in the given map.
* If the key does not exist in the map, a new {@link AtomicReference} is created and associated with the key.
* The method checks if the current value satisfies the specified predicate.
* If the predicate is satisfied, the new value is set using {@link AtomicReference#compareAndSet(Object, Object)}.
* If the update is successful and a success consumer is provided, the consumer is called with the old and new values.
* If the update is successful, the new value is returned. Otherwise, the old value is returned.
*
* @param map the map containing {@link AtomicReference} values
* @param key the key whose value is to be retrieved or updated
* @param supplier a supplier that provides the new value if the predicate is satisfied or the value is null
* @param predicate a predicate that tests the current value; if null, the update is always attempted
* @param success a consumer that is called with the old and new values if the update is successful; if null, no consumer is called
* @return the new value if the update was successful, otherwise the old value
*/
public static <K, V> V getOrUpdate(Map<K, AtomicReference<V>> map, K key, Supplier<V> supplier, Predicate<V> predicate, BiConsumer<V, V> success) {
AtomicReference<V> reference = map.computeIfAbsent(key, k -> new AtomicReference<>());
V old = reference.get();
if (predicate == null && old != null || predicate != null && predicate.test(old)) {
return old;
}
return update(reference, supplier.get(), predicate == null ? null : predicate.negate(), success);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.core.util.time;

import lombok.Getter;

/**
* Represents a time window defined by a start time and a duration.
* The end time is automatically calculated based on the start time and duration.
*/
@Getter
public class TimeWindow {

/**
* The start time of the time window.
*/
protected final long startTime;

/**
* The end time of the time window, calculated as startTime + duration.
*/
protected final long endTime;

/**
* The duration of the time window.
*/
protected final long duration;

/**
* Constructs a new TimeWindow with the specified start time and duration.
*
* @param startTime The start time of the time window.
* @param duration The duration of the time window.
*/
public TimeWindow(long startTime, long duration) {
this.startTime = startTime;
this.endTime = startTime + duration;
this.duration = duration;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.core.util.time;

import java.util.ArrayList;
import java.util.List;

/**
* A class that manages a list of TimeWindow objects.
*/
public class TimeWindowList {

/**
* The first TimeWindow added to the list.
*/
private TimeWindow window;

/**
* A list to store multiple TimeWindow objects.
*/
private List<TimeWindow> windows;

/**
* Constructs a new TimeWindowList.
*/
public TimeWindowList() {
}

/**
* Adds a TimeWindow to the list.
*
* @param window The TimeWindow to add.
*/
public void add(TimeWindow window) {
if (window != null) {
if (this.window == null) {
this.window = window;
} else if (windows == null) {
windows = new ArrayList<>();
windows.add(this.window);
windows.add(window);
} else {
windows.add(window);
}
}
}

/**
* Returns the TimeWindow with the maximum end time from the list.
* If there are multiple TimeWindows, it returns a new TimeWindow
* with the maximum start time and maximum end time from the list.
*
* @return The TimeWindow with the maximum start and end time.
*/
public TimeWindow max() {
if (windows == null) {
return window;
}
long maxStartTime = Long.MIN_VALUE;
long maxEndTime = Long.MIN_VALUE;
for (TimeWindow window : windows) {
if (window.startTime > maxStartTime) {
maxStartTime = window.startTime;
}
if (window.endTime > maxEndTime) {
maxEndTime = window.endTime;
}
}
return new TimeWindow(maxStartTime, (int) (maxEndTime - maxStartTime));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,12 @@
*/
@Getter
@Setter
public class CircuitBreakerConfig {
public class CircuitBreakerConfig extends RecyclerConfig {

/**
* The type of the circuit breaker. Default is "Resilience4j".
*/
private String type = "Resilience4j";

/**
* The interval in milliseconds at which the circuit breaker should clean up expired entries.
* Default is 30,000 milliseconds (30 seconds).
*/
private long cleanInterval = 30000;

/**
* The time in milliseconds after which the circuit breaker entries expire.
* Default is 60,000 milliseconds (60 seconds).
*/
private long expireTime = 60000;

}

Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,12 @@
*/
@Getter
@Setter
public class ConcurrencyLimiterConfig {
public class ConcurrencyLimiterConfig extends RecyclerConfig {

/**
* The type of the concurrency limiter. Default is "Resilience4j".
*/
private String type = "Resilience4j";

/**
* The interval in milliseconds at which the concurrency limiter should clean up expired entries.
* Default is 30,000 milliseconds (30 seconds).
*/
private long cleanInterval = 30000;

/**
* The time in milliseconds after which the concurrency limiter entries expire.
* Default is 60,000 milliseconds (60 seconds).
*/
private long expireTime = 60000;

}

Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,12 @@
*/
@Getter
@Setter
public class RateLimiterConfig {
public class RateLimiterConfig extends RecyclerConfig {

/**
* The type of the rate limiter.
*/
private String type;

/**
* The interval in milliseconds at which the rate limiter should clean up expired entries.
* Default is 30,000 milliseconds (30 seconds).
*/
private long cleanInterval = 30000;

/**
* The time in milliseconds after which the rate limiter entries expire.
* Default is 60,000 milliseconds (60 seconds).
*/
private long expireTime = 60000;

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.governance.config;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public abstract class RecyclerConfig {
/**
* The interval in milliseconds at which the concurrency limiter should clean up expired entries.
* Default is 30,000 milliseconds (30 seconds).
*/
protected long cleanInterval = 30000;

/**
* The time in milliseconds after which the concurrency limiter entries expire.
* Default is 60,000 milliseconds (60 seconds).
*/
protected long expireTime = 60000;
}
Loading

0 comments on commit 59fc39c

Please sign in to comment.