sentnel中启动时要加相关参数,所以自己写一个springboot的自动配置
项目目录

image.png
pom文件依赖(项目名称和sentinel的版本自己加)
<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-dubbo-adapter</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-zookeeper</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-api-gateway-adapter-common</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-client-default</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-server-default</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
代码
@Configuration
@EnableConfigurationProperties(SentinelProperties.class)
public class SentinelConfiguration implements InitializingBean {
public static final String LOG_DIR_PROP = "csp.sentinel.log.dir";
public static final String PRO_NAME_PROP = "project.name";
public static final String APP_NAME_PROP = "spring.application.name";
public static final String DUBBO_PRO = "java.net.preferIPv4Stack";
@Autowired
private SentinelProperties sentinelProperties;
@Autowired
private Environment env;
// 为了让默认异常注册代码优先执行
// static {
// ExceptionRegistry.updateForPackage("com.xmutca.sentinel.dubbo.starter.exception");
// }
/**
* 熔断器注解支持
*
* @return
*/
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
@Override
public void afterPropertiesSet() throws Exception {
// 设置日志地址
if (StringUtil.isBlank(System.getProperty(LOG_DIR_PROP))
&& StringUtil.isNotBlank(sentinelProperties.getApplication().getLogDir())) {
System.setProperty(LOG_DIR_PROP, sentinelProperties.getApplication().getLogDir());
}
// 设置项目名称
if (StringUtil.isBlank(System.getProperty(PRO_NAME_PROP))) {
String name = env.getProperty(PRO_NAME_PROP);
if (StringUtil.isBlank(name)) {
name = sentinelProperties.getApplication().getName();
}
if (StringUtil.isBlank(name)) {
name = env.getProperty(APP_NAME_PROP);
}
if (StringUtil.isNotBlank(name)) {
System.setProperty(PRO_NAME_PROP, name);
}
}
if (StringUtil.isBlank(System.getProperty(DUBBO_PRO))) {
if (sentinelProperties.getApplication().isDubbo()) {
System.setProperty(DUBBO_PRO, "true");
}
}
// 设置主页
if (StringUtil.isNotBlank(sentinelProperties.getApplication().getDashboard())) {
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, sentinelProperties.getApplication().getDashboard());
}
// 设置端口
if (StringUtil.isNotBlank(sentinelProperties.getApplication().getPort())) {
SentinelConfig.setConfig(TransportConfig.SERVER_PORT, sentinelProperties.getApplication().getPort());
}
// 注册降级统一返回码
WebCallbackManager.setUrlBlockHandler(new SnfGlobalUrlBlockHandler());
}
/**
* zookeeper的datasource注册
*/
@Configuration
@ConditionalOnProperty(name = "sentinel.zookeeper.enable", havingValue = "true")
public class ZookeeperDataSourceConfiguration implements InitializingBean {
// 要与sentinel-dashboard中的路由规则相匹配
public static final String FLOW_RULE_PATH = "/sentinel_rule_config/%s/flow";
public static final String AUTHORITY_RULE_PATH = "/sentinel_rule_config/%s/authority";
public static final String DEGRADE_RULE_PATH = "/sentinel_rule_config/%s/degrade";
public static final String PARAM_FLOW_RULE_PATH = "/sentinel_rule_config/%s/param";
public static final String SYSTEM_RULE_PATH = "/sentinel_rule_config/%s/system";
public static final String GATEWAY_RULE_PATH = "/sentinel_rule_config/%s/gateway";
public static final String GATEWAY_API_RULE_PATH = "/sentinel_rule_config/%s/apidefinition";
@Override
public void afterPropertiesSet() throws Exception {
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(FLOW_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
ReadableDataSource<String, List<AuthorityRule>> authorityRleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(AUTHORITY_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>() {
}));
AuthorityRuleManager.register2Property(authorityRleDataSource.getProperty());
ReadableDataSource<String, List<DegradeRule>> degradeRleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(DEGRADE_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
}));
DegradeRuleManager.register2Property(degradeRleDataSource.getProperty());
ReadableDataSource<String, List<ParamFlowRule>> paramFlowRleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(PARAM_FLOW_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {
}));
ParamFlowRuleManager.register2Property(paramFlowRleDataSource.getProperty());
ReadableDataSource<String, List<SystemRule>> systemRuleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(SYSTEM_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
}));
SystemRuleManager.register2Property(systemRuleDataSource.getProperty());
ReadableDataSource<String, Set<GatewayFlowRule>> gatewayRuleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(GATEWAY_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<Set<GatewayFlowRule>>() {
}));
GatewayRuleManager.register2Property(gatewayRuleDataSource.getProperty());
ReadableDataSource<String, Set<ApiDefinition>> gatewayApiRuleDataSource = new ZookeeperDataSource<>(sentinelProperties.getZookeeper().getAddress(),
String.format(GATEWAY_API_RULE_PATH, AppNameUtil.getAppName()),
source -> JSON.parseObject(source, new TypeReference<Set<ApiDefinition>>() {
}));
GatewayApiDefinitionManager.register2Property(gatewayApiRuleDataSource.getProperty());
}
}
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
registration.setName("sentinelFilter");
registration.setOrder(1);
// If this is enabled, the entrance of all Web URL resources will be unified as a single context name.
// In most scenarios that's enough, and it could reduce the memory footprint.
registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "true");
return registration;
}
}
@ConfigurationProperties(prefix = "sentinel")
public class SentinelProperties {
/**
* 应用配置
*/
private ApplicationProperties application;
/**
* zk配置
*/
private ZookeeperProperties zookeeper;
public void setApplication(ApplicationProperties application) {
this.application = application;
}
public ZookeeperProperties getZookeeper() {
return zookeeper;
}
public void setZookeeper(ZookeeperProperties zookeeper) {
this.zookeeper = zookeeper;
}
/**
* 应用配置
*/
public static class ApplicationProperties {
/**
* 客户端的 port,用于上报相关信息(默认为 8719), 同台机器上由多台时,需要指定不同的端口
*/
private String port;
/**
* 控制台的地址 IP + 端口
*/
private String dashboard;
/**
* 应用名称,会在控制台中显示
*/
private String name;
/**
* 日志地址
*/
private String logDir;
/**
* 是否为dubbo服务
*/
private boolean dubbo;
public boolean isDubbo() {
return dubbo;
}
public void setDubbo(boolean dubbo) {
this.dubbo = dubbo;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getDashboard() {
return dashboard;
}
public void setDashboard(String dashboard) {
this.dashboard = dashboard;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLogDir() {
return logDir;
}
public void setLogDir(String logDir) {
this.logDir = logDir;
}
}
/**
* zookeeper配置文件
*/
public static class ZookeeperProperties {
/**
* 服务器地址
*/
private String address;
/**
* 睡眠时间
*/
private int sleepTimeMs = 100;
/**
* 最大重试
*/
private int maxRetries = 3;
/**
* 是否开启
*/
private boolean enable;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getSleepTimeMs() {
return sleepTimeMs;
}
public void setSleepTimeMs(int sleepTimeMs) {
this.sleepTimeMs = sleepTimeMs;
}
public int getMaxRetries() {
return maxRetries;
}
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
}
public ApplicationProperties getApplication() {
if (null == application) {
application = new ApplicationProperties();
}
return application;
}
}
- SnfGlobalUrlBlockHandler(全局降级返回参数)
public class SnfGlobalUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
Result errorMsg = new Result();
// 限流
if(e instanceof FlowException){
errorMsg.setStatus(Result.Status.FLOW_ERR);
errorMsg.setMessage("限流了");
}
// 降级
else if(e instanceof DegradeException){
errorMsg.setStatus(Result.Status.DEGRADE_ERR);
errorMsg.setMessage("限流了");
}
// 参数热点
else if(e instanceof ParamFlowException){
errorMsg.setStatus(Result.Status.PARAM_FLOW_ERR);
errorMsg.setMessage("热点参数限流");
}
// 系统异常
else if(e instanceof SystemBlockException){
errorMsg.setStatus(Result.Status.SYSTEM_ERR);
errorMsg.setMessage("系统规则(负载,...)不满足规则");
}
// 授权异常
else if(e instanceof AuthorityException){
errorMsg.setStatus(Result.Status.AUTHORITY_ERR);
errorMsg.setMessage("授权规则不通过");
}
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setHeader("Content-Type","application/json;charset=utf-8");
httpServletResponse.setContentType("application/json;charset=utf-8");
new ObjectMapper().writeValue(httpServletResponse.getWriter(),errorMsg);
}
}
public class Result<T> implements Serializable {
/**
* 默认
*/
public final static Result DEFAULT_ERROR_RESULT = new Result<>(Result.Status.ERROR, "系统开小差,熔断降级处理。");
public enum Status {
/**
* 限流
*/
FLOW_ERR(101),
/**
* 降级
*/
DEGRADE_ERR(102),
/**
* 参数热点
*/
PARAM_FLOW_ERR(103),
/**
* 授权
*/
AUTHORITY_ERR(104),
/**
* 系统
*/
SYSTEM_ERR(105),
/**
* 业务处理成功
*/
SUCCESS(200),
/**
* 页面重定向
*/
REDIRECT(302),
/**
* 错误请求
*/
BAD_REQUEST(400),
/**
* 请进行登陆
*/
UNAUTHORIZED(401),
/**
* 权限代码
*/
FORBIDDEN(403),
/**
* 页面不存在
*/
NOT_FOUND(404),
/**
* 无法满足条件的,认定为攻击
*/
NOT_ACCEPTABLE(406),
/**
* 请求超时
*/
REQUEST_TIMEOUT(408),
/**
* 请求过多降级
*/
TOO_MANY_REQUESTS(429),
/**
* 业务访问失败
*/
ERROR(500),
/**
* 请求失败
*/
BAD_GATEWAY(502),
/**
* 网关超时
*/
GATEWAY_TIMEOUT(504);
private int code;
Status(int code) {
this.code = code;
}
public int getCode() {
return code;
}
@Override
public String toString() {
return String.valueOf(getCode());
}
public static Status getInstance(int code) {
Optional<Status> op = Arrays.asList(Status.values()).parallelStream().filter(currentStatus -> currentStatus.code == code).findFirst();
if (op.isPresent()) {
return op.get();
}
return null;
}
}
/**
* 消息
*/
private String message;
/**
* 状态
*/
private Status status = Status.SUCCESS;
/**
* 时间戳
*/
private Long timestamp = System.currentTimeMillis();
/**
* 数据
*/
private T result;
/**
* 扩展信息
*/
private Object extra;
public static Result getDefaultErrorResult() {
return DEFAULT_ERROR_RESULT;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
public Object getExtra() {
return extra;
}
public void setExtra(Object extra) {
this.extra = extra;
}
public Result() {
}
public Result(Status status) {
this.status = status;
}
public Result(T result) {
this.result = result;
}
public Result(Status status, String message) {
this.status = status;
this.message = message;
}
public Result(Status status, T result) {
this.status = status;
this.result = result;
}
public Result(String message, T result) {
this.result = result;
this.message = message;
}
public Result(Status status, String message, T result) {
this.status = status;
this.message = message;
this.result = result;
}
public int getStatus() {
return status.getCode();
}
public Status getStatusEnum() {
return status;
}
public void setStatusEnum(Status status) {
this.status = status;
}
public void setStatus(int status) {
this.status = Status.getInstance(status);
}
public void setStatus(Status status) {
this.status = status;
}
}
- SentinelAutoConfiguration
/**
* @version
* @author: zhongjias
* @Date:
*/
@Configuration
@Import(SentinelConfiguration.class)
public class SentinelAutoConfiguration {
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
xxx.xx.xx.SentinelAutoConfiguration (SentinelAutoConfiguration的路径)
使用时,工程引入这个starter,配置文件加入以下

image.png
网友评论