
com.fizzgate.plugin.auth.GatewayGroupService Maven / Gradle / Ivy
/*
* Copyright (C) 2020 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.fizzgate.plugin.auth;
import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.stereotype.Service;
import com.fizzgate.config.AggregateRedisConfig;
import com.fizzgate.util.Consts;
import com.fizzgate.util.JacksonUtils;
import com.fizzgate.util.NetworkUtils;
import com.fizzgate.util.ReactorUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author hongqiaowei
*/
@Service
public class GatewayGroupService {
private static final Logger log = LoggerFactory.getLogger(GatewayGroupService.class);
private static final String fizzGatewayGroup = "fizz_gateway_group";
private static final String fizzGatewayGroupChannel = "fizz_gateway_group_channel";
public Map gatewayGroupMap = new HashMap<>(8);
private Map oldGatewayGroupMap = new HashMap<>(8);
public Set currentGatewayGroupSet = Stream.of(GatewayGroup.DEFAULT).collect(Collectors.toSet());
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
private ReactiveStringRedisTemplate rt;
@Resource
private Environment environment;
@PostConstruct
public void init() throws Throwable {
this.init(this::lsnGatewayGroupChange);
}
public void refreshLocalCache() throws Throwable {
this.init(null);
}
private void init(Supplier> doAfterLoadCache) throws Throwable {
Map gatewayGroupMapTmp = new HashMap<>(8);
Map oldGatewayGroupMapTmp = new HashMap<>(8);
Set currentGatewayGroupSetTmp = Stream.of(GatewayGroup.DEFAULT).collect(Collectors.toSet());
final Throwable[] throwable = new Throwable[1];
Throwable error = Mono.just(Objects.requireNonNull(rt.opsForHash().entries(fizzGatewayGroup)
.defaultIfEmpty(new AbstractMap.SimpleEntry<>(ReactorUtils.OBJ, ReactorUtils.OBJ)).onErrorStop().doOnError(t -> {
log.info(null, t);
})
.concatMap(e -> {
Object k = e.getKey();
if (k == ReactorUtils.OBJ) {
return Flux.just(e);
}
String json = (String) e.getValue();
// log.info(json, LogService.BIZ_ID, k.toString());
ThreadContext.put(Consts.TRACE_ID, k.toString());
log.info(json);
try {
GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class);
oldGatewayGroupMapTmp.put(gg.id, gg);
updateGatewayGroupMap(gg, gatewayGroupMapTmp, currentGatewayGroupSetTmp);
return Flux.just(e);
} catch (Throwable t) {
throwable[0] = t;
log.info(json, t);
return Flux.error(t);
}
}).blockLast())).flatMap(
e -> {
if (throwable[0] != null) {
return Mono.error(throwable[0]);
}
if (doAfterLoadCache != null) {
return doAfterLoadCache.get();
} else {
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
}
}
).block();
if (error != ReactorUtils.EMPTY_THROWABLE) {
throw error;
}
gatewayGroupMap = gatewayGroupMapTmp;
oldGatewayGroupMap = oldGatewayGroupMapTmp;
currentGatewayGroupSet = currentGatewayGroupSetTmp;
}
private Mono lsnGatewayGroupChange() {
final Throwable[] throwable = new Throwable[1];
final boolean[] b = {false};
rt.listenToChannel(fizzGatewayGroupChannel).doOnError(t -> {
throwable[0] = t;
b[0] = false;
log.error("lsn " + fizzGatewayGroupChannel, t);
}).doOnSubscribe(
s -> {
b[0] = true;
log.info("success to lsn on " + fizzGatewayGroupChannel);
}
).doOnNext(msg -> {
String json = msg.getMessage();
// log.info(json, LogService.BIZ_ID, "gg" + System.currentTimeMillis());
ThreadContext.put(Consts.TRACE_ID, "gg" + System.currentTimeMillis());
log.info(json);
try {
GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class);
GatewayGroup r = oldGatewayGroupMap.remove(gg.id);
if (!gg.isDeleted && r != null) {
gatewayGroupMap.remove(r.group);
}
updateGatewayGroupMap(gg, gatewayGroupMap, currentGatewayGroupSet);
if (!gg.isDeleted) {
oldGatewayGroupMap.put(gg.id, gg);
}
} catch (Throwable t) {
log.info(json, t);
}
}).subscribe();
Throwable t = throwable[0];
while (!b[0]) {
if (t != null) {
return Mono.error(t);
} else {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
return Mono.error(e);
}
}
}
return Mono.just(ReactorUtils.EMPTY_THROWABLE);
}
private void updateGatewayGroupMap(GatewayGroup gg, Map gatewayGroupMap, Set currentGatewayGroupSet) {
if (gg.isDeleted) {
GatewayGroup r = gatewayGroupMap.remove(gg.group);
log.info("remove " + r);
} else {
GatewayGroup existGatewayGroup = gatewayGroupMap.get(gg.group);
gatewayGroupMap.put(gg.group, gg);
if (existGatewayGroup == null) {
log.info("add " + gg);
} else {
log.info("update " + existGatewayGroup + " with " + gg);
}
}
updateCurrentGatewayGroupSet(currentGatewayGroupSet, gatewayGroupMap);
}
private void updateCurrentGatewayGroupSet(Set currentGatewayGroupSet, Map gatewayGroupMap) {
Set ips = NetworkUtils.getServerIps();
String applicationName = environment.getProperty("spring.application.name");
currentGatewayGroupSet.clear();
gatewayGroupMap.forEach(
(k, gg) -> {
Set set = new HashSet<>(ips);
set.retainAll(gg.gateways);
if (!set.isEmpty() || gg.gateways.contains(applicationName)) {
currentGatewayGroupSet.add(gg.group);
}
}
);
if (currentGatewayGroupSet.isEmpty()) {
currentGatewayGroupSet.add(GatewayGroup.DEFAULT);
}
// publish event
}
public GatewayGroup get(String gg) {
return gatewayGroupMap.get(gg);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy