跳到主要内容

(六) 控制台和客户端通信原理

控制台

控制台主要的处理类是 FlowControllerV1

@RestController
@RequestMapping(value = "/v1/flow")
public class FlowControllerV1 {



private final Logger logger = LoggerFactory.getLogger(FlowControllerV1.class);

@Autowired
private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;

@Autowired
private SentinelApiClient sentinelApiClient;

@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app,
@RequestParam String ip,
@RequestParam Integer port) {



if (StringUtil.isEmpty(app)) {


return Result.ofFail(-1, "app can't be null or empty");
}
if (StringUtil.isEmpty(ip)) {


return Result.ofFail(-1, "ip can't be null or empty");
}
if (port == null) {


return Result.ofFail(-1, "port can't be null");
}
try {


List<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {


logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}

private <R> Result<R> checkEntityInternal(FlowRuleEntity entity) {


if (StringUtil.isBlank(entity.getApp())) {


return Result.ofFail(-1, "app can't be null or empty");
}
if (StringUtil.isBlank(entity.getIp())) {


return Result.ofFail(-1, "ip can't be null or empty");
}
if (entity.getPort() == null) {


return Result.ofFail(-1, "port can't be null");
}
if (StringUtil.isBlank(entity.getLimitApp())) {


return Result.ofFail(-1, "limitApp can't be null or empty");
}
if (StringUtil.isBlank(entity.getResource())) {


return Result.ofFail(-1, "resource can't be null or empty");
}
if (entity.getGrade() == null) {


return Result.ofFail(-1, "grade can't be null");
}
if (entity.getGrade() != 0 && entity.getGrade() != 1) {


return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
}
if (entity.getCount() == null || entity.getCount() < 0) {


return Result.ofFail(-1, "count should be at lease zero");
}
if (entity.getStrategy() == null) {


return Result.ofFail(-1, "strategy can't be null");
}
if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {


return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
}
if (entity.getControlBehavior() == null) {


return Result.ofFail(-1, "controlBehavior can't be null");
}
int controlBehavior = entity.getControlBehavior();
if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {


return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
}
if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {


return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
}
if (entity.isClusterMode() && entity.getClusterConfig() == null) {


return Result.ofFail(-1, "cluster config should be valid");
}
return null;
}

@PostMapping("/rule")
@AuthAction(PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {


Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {


return checkResult;
}
entity.setId(null);
Date date = new Date();
entity.setGmtCreate(date);
entity.setGmtModified(date);
entity.setLimitApp(entity.getLimitApp().trim());
entity.setResource(entity.getResource().trim());
try {


entity = repository.save(entity);

publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
return Result.ofSuccess(entity);
} catch (Throwable t) {


Throwable e = t instanceof ExecutionException ? t.getCause() : t;
logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
return Result.ofFail(-1, e.getMessage());
}
}

@PutMapping("/save.json")
@AuthAction(PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiUpdateFlowRule(Long id, String app,
String limitApp, String resource, Integer grade,
Double count, Integer strategy, String refResource,
Integer controlBehavior, Integer warmUpPeriodSec,
Integer maxQueueingTimeMs) {


if (id == null) {


return Result.ofFail(-1, "id can't be null");
}
FlowRuleEntity entity = repository.findById(id);
if (entity == null) {


return Result.ofFail(-1, "id " + id + " dose not exist");
}
if (StringUtil.isNotBlank(app)) {


entity.setApp(app.trim());
}
if (StringUtil.isNotBlank(limitApp)) {


entity.setLimitApp(limitApp.trim());
}
if (StringUtil.isNotBlank(resource)) {


entity.setResource(resource.trim());
}
if (grade != null) {


if (grade != 0 && grade != 1) {


return Result.ofFail(-1, "grade must be 0 or 1, but " + grade + " got");
}
entity.setGrade(grade);
}
if (count != null) {


entity.setCount(count);
}
if (strategy != null) {


if (strategy != 0 && strategy != 1 && strategy != 2) {


return Result.ofFail(-1, "strategy must be in [0, 1, 2], but " + strategy + " got");
}
entity.setStrategy(strategy);
if (strategy != 0) {


if (StringUtil.isBlank(refResource)) {


return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
}
entity.setRefResource(refResource.trim());
}
}
if (controlBehavior != null) {


if (controlBehavior != 0 && controlBehavior != 1 && controlBehavior != 2) {


return Result.ofFail(-1, "controlBehavior must be in [0, 1, 2], but " + controlBehavior + " got");
}
if (controlBehavior == 1 && warmUpPeriodSec == null) {


return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
}
if (controlBehavior == 2 && maxQueueingTimeMs == null) {


return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
}
entity.setControlBehavior(controlBehavior);
if (warmUpPeriodSec != null) {


entity.setWarmUpPeriodSec(warmUpPeriodSec);
}
if (maxQueueingTimeMs != null) {


entity.setMaxQueueingTimeMs(maxQueueingTimeMs);
}
}
Date date = new Date();
entity.setGmtModified(date);
try {


entity = repository.save(entity);
if (entity == null) {


return Result.ofFail(-1, "save entity fail: null");
}

publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
return Result.ofSuccess(entity);
} catch (Throwable t) {


Throwable e = t instanceof ExecutionException ? t.getCause() : t;
logger.error("Error when updating flow rules, app={}, ip={}, ruleId={}", entity.getApp(),
entity.getIp(), id, e);
return Result.ofFail(-1, e.getMessage());
}
}

@DeleteMapping("/delete.json")
@AuthAction(PrivilegeType.WRITE_RULE)
public Result<Long> apiDeleteFlowRule(Long id) {



if (id == null) {


return Result.ofFail(-1, "id can't be null");
}
FlowRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {


return Result.ofSuccess(null);
}

try {


repository.delete(id);
} catch (Exception e) {


return Result.ofFail(-1, e.getMessage());
}
try {


publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);
return Result.ofSuccess(id);
} catch (Throwable t) {


Throwable e = t instanceof ExecutionException ? t.getCause() : t;
logger.error("Error when deleting flow rules, app={}, ip={}, id={}", oldEntity.getApp(),
oldEntity.getIp(), id, e);
return Result.ofFail(-1, e.getMessage());
}
}

private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {


List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}
}