camellia-feign
join camellia-core and open-feign, so your feign-client have this feature:
- support dynamic route
- support custom route by request param
- support custom load balance policy by request param
- support read-write-separate/double-write
- support dynamic conf, such like timeout
支持 动态路 由 ,运行期 间支持 动态配置 新 的 路 由 规则支持 camellia-core的 通用 能力 ,如读写 分 离、双 写 支持 熔断(集成 了 CamelliaCircuitBreaker)支持 fallback(支持 fallback和 fallbackFactory)支持 根 据 租户id配置 不同 的 路 由 (使用 注解 的 方式 标识租户id,无侵入 性 )支持 动态配置 (包括 超 时时间、熔断配置 )支持 动态识别openFeign和 spring-cloud-feign的 注解 支持 spring-boot-starter,可 以一键替换spring-cloud-feign
先 定 义一个接口 类
@CamelliaFeignClient(route = "feign#http://127.0.0.1:8080", fallback = TestFeignServiceFallback.class)
public interface ITestFeignService {
@RequestMapping(value = "/getUser", method = RequestMethod.POST)
UserResponse getUser(User user);
}
在 启动类上启动camellia-feign
@SpringBootApplication
@EnableCamelliaFeignClients(basePackages = {"com.netease.nim.camellia.feign.samples"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
通 过@Autowired自 动注入 service
@RestController
public class TestFeignController {
@Autowired
private ITestFeignService testFeignService;
//.....
}
#固定 url
##支持 http
feign#http://127.0.0.1:8080
##也支持 https
feign#https://www.abc.com
#基 于注册 中心
##支持 http
feign-discovery#http://serviceName
##也支持 https
feign-discovery#https://serviceName
此外,
你可以
public class CamelliaFeignClientFactory {
/**
* 构造方法
* @param feignEnv 一 些全局 参 数 :包括 camellia-core的 一 些基本 参 数 、使用 注 册 中心 时需要 的 discovery实现以及对应的 健康 检查方法 、使用 fallback和 熔断时过滤异常 类型的 FallbackExceptionChecker
* @param camelliaApi 接 入 camellia-dashboard时需要 本 参 数
* @param checkIntervalMillis 接 入 camellia-dashboard时的规则检查周期 ,默 认5000ms
* @param feignProps 构造feign客 户端时的参 数 ,包括 编解码类型 、异常处理类等
* @param dynamicOptionGetter 动态配置 的 回 调接口
*/
public CamelliaFeignClientFactory(CamelliaFeignEnv feignEnv, CamelliaApi camelliaApi, long checkIntervalMillis,
CamelliaFeignProps feignProps, CamelliaFeignDynamicOptionGetter dynamicOptionGetter) {
this.feignProps = feignProps;
this.feignEnv = feignEnv;
this.camelliaApi = camelliaApi;
this.checkIntervalMillis = checkIntervalMillis;
this.dynamicOptionGetter = dynamicOptionGetter;
}
/**
* 生成 一 个camellia-feign客 户端
* @param apiType 类型
* @return 客 户端实例
*/
public <T> T getService(Class<T> apiType) {
//...
}
/**
* 生成 一 个camellia-feign客 户端
* @param apiType 类型
* @param fallback fallback
* @return 客 户端实例
*/
public <T> T getService(Class<T> apiType, T fallback) {
//...
}
//.....
}
public interface CamelliaFeignDynamicOptionGetter {
/**
* 根 据 bid和 bgroup获取动态配置
* @param bid 业务bid
* @param bgroup 业务bgroup
* @return DynamicOption
*/
DynamicOption getDynamicOption(long bid, String bgroup);
/**
* 根 据 bid获取DynamicRouteConfGetter
* @param bid 业务bid
* @return DynamicRouteConfGetter
*/
default DynamicRouteConfGetter getDynamicRouteConfGetter(long bid) {
return null;
}
}
DynamicOption
public class DynamicOption {
//连接超 时配置
private DynamicValueGetter<Long> connectTimeout;
private DynamicValueGetter<TimeUnit> connectTimeoutUnit;
//读超时配置
private DynamicValueGetter<Long> readTimeout;
private DynamicValueGetter<TimeUnit> readTimeoutUnit;
//是 否 支持 重定 向
private DynamicValueGetter<Boolean> followRedirects;
//是 否 开启监控
private DynamicValueGetter<Boolean> monitorEnable;
//是 否 开启熔断,若 circuitBreakerConfig为null,则不开启熔断
private CircuitBreakerConfig circuitBreakerConfig;
//动态检查feign的 注解 类型,当 前 支持 默 认注解 和 spring-mvc注解 ,默 认支持 动态监测
private DynamicContractTypeGetter dynamicContractTypeGetter = new DynamicContractTypeGetter.Default();
//当 基 于注册 中心 时,如何 选择服 务节点 ,默 认随机 ,支持 哈希以及其他自 定 义规则,功 能 类似于一个简单的ribbon
private CamelliaServerSelector<FeignResource> serverSelector = new RandomCamelliaServerSelector<>();
//.....
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface CamelliaFeignClient {
long bid() default -1;//业务bid,默 认-1,若 路 由 规则委 托 给camellia-dashboard,则bid需要 大 于0
String bgroup() default "default";//业务bgroup
String route() default "";//如果路 由 没 有 委 托 给camellia-dashboard,则本字 段 必填
String[] qualifiers() default {};//仅给camellia-feign-spring-boot-starter使用
boolean primary() default true;//仅给camellia-feign-spring-boot-starter使用
//如果使用 camellia-feign-spring-boot-starter,则会优先去 spring工 厂取,如果取 不 到 ,则尝试使用 无参构造方法 建 一 个
//正常 使用 CamelliaFeignClientFactory的 话,则会优先使用 传入的 fallback,否 则尝试使用 无参构造方法 建 一 个
Class<?> fallback() default void.class;
//fallbackFactory的 优先级高于fallback
Class<?> fallbackFactory() default void.class;
}
camellia
public class User {
@RouteKey
private long tenantId;
@LoadBalanceKey
private long uid;
private String name;
private String ext;
//.....
}
以快
public class SampleDynamicRouteConfGetter implements DynamicRouteConfGetter {
@Override
public String bgroup(Object routeKey) {
if (routeKey == null) return "default";
if (String.valueOf(routeKey).equals("1")) {
return "bgroup1";
} else if (String.valueOf(routeKey).equals("2")) {
return "bgroup2";
}
return "default";
}
}
1)
2)
3)其他
- 负载
均衡 策略 的 含义是 指 在 使用 注 册 中心 进行节点的 自 动发现的模 式 下 ,在 同 一个路由规则下,针对多 个服务节点 ,如何 将 请求分 发到具体 某 个节点 - 设置负载
均衡 器 策略 的 方法 通 过设置 DynamicOption下 的 CamelliaServerSelector参 数 来 实现,默 认是随 机 策略 ,此外还内置 了 哈希策略 ,可 以按需选择
public interface CamelliaServerSelector<T> {
/**
*
* @param list 待 选择的 节点列 表
* @param loadBalanceKey 负载均衡 key
* @return 具体 选择哪个节点
*/
T pick(List<T> list, Object loadBalanceKey);
}
camellia-feign
CamelliaCircuitBreaker
public class CircuitBreakerConfig {
//以下 参 数 一经设置不可修改
private String name = "camellia-circuit-breaker";//熔断器 的 别名
private long statisticSlidingWindowTime = 10 * 1000L;//统计成功 失 败的滑 动窗口 的 大小 ,单位ms,默 认10s
private int statisticSlidingWindowBucketSize = 10;//滑 动窗口 分割 为多少 个bucket,默 认10个
//以下 参 数 可 以动态修改
private DynamicValueGetter<Boolean> enable = () -> true;//是 否 启用,若 不 启用,则不进行失 败率统计,所有 请求都 允 许
private DynamicValueGetter<Boolean> forceOpen = () -> false;//强制 打 开,则所有 请求都 不 允 许
private DynamicValueGetter<Double> failThresholdPercentage = () -> 0.5;//滑 动窗口 范围内 失 败比例 超 过多少 触 发熔断 ,默 认50%
private DynamicValueGetter<Long> requestVolumeThreshold = () -> 20L;//滑 动窗口内 至 少 多少 个请求 才 会 触 发熔断 ,默 认20个
private DynamicValueGetter<Long> singleTestIntervalMillis = () -> 5000L;//当 熔断器 打 开的情 况下,间隔多久 尝试一 次 探 测(也就是 半 开)
private DynamicValueGetter<Boolean> logEnable = () -> true;//是 否 打 开日志 (主要 是 打 印 熔断器 状 态变更 时打印
//.....
}
camellia-feign
- spring
自 动注入 的 fallbackFactory实例 - spring
自 动注入 的 fallback实例 - 尝试
使用 无参构造方法 去 初 始 化 注解 中 fallbackFactory实例 - 尝试
使用 无参构造方法 去 初 始 化 注解 中 fallback实例
- camellia-feign
使用 DynamicValueGetter的 方式 来 提供 动态参 数 ,你可以自行 实现(如对接 到 你们的 配置 中心 ) - camellia-feign
默 认使用 DefaultCamelliaFeignDynamicOptionGetter来 获取动态参 数 ,此时参 数 实际上 是 静 态的 - 此外,camellia-feign还
提供 了 一 个FileBasedCamelliaFeignDynamicOptionGetter,支持 使用 本地 配置 文 件 (properties)来 动态修 改 参 数
一般 来 说,你需要 引入camellia-dashboard来 配置 和 下 发动态的路 由 配置 - 此外你也
可 以使用 FileBasedCamelliaApi,从而使用 本地 配置 文 件 (properties)来 模 拟camellia-dashboard