高性能的秘密武器:Redis在Spring Cloud Config中的妙用

在我们之前的有一节文中说了使用redisson组件的使用。Java分布式开发利器-Redisson,那以此为基础,我们使用redisson组件作为配置微服务的配置中心,使我们的微服务配置库变为redis。

全网很少使用redis mysql等等作为配置库的例子,大部分使用阿里巴巴的开源框架Nacos,我见过很小很小的项目,做了一个很大很大的框架,咱也不清楚这个项目是怎么弄的,小项目大框架,真的是为了显示自己的能力,还是给开发人员增加工作量呢。

按照我的理解:小就做小巧点,整的那么大,冗余复杂,俩个字:难受

废话不多说,我们来配置看看如何使用redis作为配置中心。

1.  理解Spring Cloud Config中的EnvironmentRepository

在Spring Cloud Config中,EnvironmentRepository 是一个接口,它提供了从配置服务中检索环境变量和配置信息的功能。这个接口是 Spring Cloud Config 组件的一部分,它使得应用程序能够从外部配置源(如Git仓库或文件系统)中读取配置,而无需将这些配置硬编码到应用程序中。

EnvironmentRepository 通常与 Spring Cloud Config Server 一起使用,后者负责提供配置服务的存储和接口。当应用程序启动时,它会连接到配置服务,并从配置服务中加载其所需的配置。

我们这里举一个简单的示例,展示如何在 Spring 应用程序中EnvironmentRepository:

import org.springframework.cloud.config.EnvironmentRepository;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class MyEnvironmentRepository implements EnvironmentRepository {

    @Override
    public Environment findOne(String application, String profile, String label) {
        // 这里可以添加自定义逻辑来获取配置信息
        return new Environment(application, profile); // 返回从配置服务中获取的配置信息
    }
}

既然我们了解到EnvironmentRepository,那么我们就可以用这个接口的实现来实现获取redis中的配置信息了。

2. 完成config配置

目前不用心急,我们在创建了spring cloud config项目工程之后,我们需要在它的配置中,明确告诉config,我用的是redis。

还有配置就是连接redis配置,我们采用的redisson的实现,所以请查看Java分布式开发利器-Redisson即可实现。

spring.application.name=office-config-manager
server.port=10051
spring.profiles.active=redis

3. 完成实现

首先完成一个查询redis配置信息字段的实现类,实现类完全按照config中的 application,profile,label的字段进行获取。

    // redission链接
    @Resource
    private RedissonClient redissonClient;
    // 配置获取项前缀 如:redis内的配置为 myconfig:dev:dao, 
    // 那么“myconfig:”就是 prefix的字段
    // dev就是 label的字段
    // profile 就是 dao字段
    @Value("${spring.cloud.redis.profile.prefix}")
    private String prefix;

    /**
     * <b>功能描述:</b>获取配置信息<br>
     * <b>修订记录:</b><br>
     * @param application
     * @param profile
     * @param label
     */
    @Override
    public String getRedisPropertiesValue(String application, String profile, String label) {
        RBucket<String> configMap = redissonClient.getBucket(prefix + label + ":" + profile);
        return configMap != null && configMap.isExists() ? configMap.get() : null;
    }

完成了获取配置的接口,我们完成EnvironmentRepository的实现类。

@Slf4j
public class RedissonEnvironmentRepository implements EnvironmentRepository, Ordered {

    @Resource
    private IRedissonService redissonService;

    private static final String REF_CONF_KEY = "conf-ref";


    @Override
    public Environment findOne(String application, String profile, String label) {
        if (StringUtils.isEmpty(application) || StringUtils.isEmpty(profile)) {
            return null;
        }
        String modelValueJson = redissonService.getRedisPropertiesValue(application, profile, label);
        if (modelValueJson != null) {
            // 主配置获取
            Environment environment = new Environment(application, StringUtils.commaDelimitedListToStringArray(profile), label, null, null);
            Map<String, String> config = getProDataMap(modelValueJson);
            environment.add(new PropertySource(label + "/" + application + "-" + profile, config));
            //获取需关联的配置
            if (config != null && !config.isEmpty() && config.containsKey(REF_CONF_KEY)) {
                String ref = config.get(REF_CONF_KEY) == null ? "" : config.get(REF_CONF_KEY);
                List<String> confRef = Splitter.on(",").splitToList(ref);
                for (String profile_ : confRef) {
                    modelValueJson = redissonService.getRedisPropertiesValue(application, profile_, label);
                    if (modelValueJson != null && !modelValueJson.isEmpty()) {
                        Map<String, String> refConfig = getProDataMap(modelValueJson);
                        environment.add(new PropertySource(label + "/" + application + "-" + profile_, refConfig));
                    } else {
                        log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                        log.info("[{}]配置未获取到,请检查", profile_);
                        log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                    }
                }
            }
            return environment;
        }
        return new Environment(application, profile);
    }

    @Override
    public int getOrder() {
        return 0;
    }


    /**
     * <b>功能描述:</b>获取properties文件中的内容,并返回map<br>
     * <b>修订记录:</b><br>
     *
     * @return
     */
    public static Map<String, String> getProDataMap(String proStr) {
        Map<String, String> map = new HashMap<>();
        Properties pro = new Properties();
        Reader reader = null;
        try {
            reader = new StringReader(proStr);
            pro.load(reader);
        } catch (UnsupportedEncodingException e) {
            log.error("读取失败", e);
        } catch (IOException e) {
            log.error("读取失败", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                }
            }
        }
        Set<Map.Entry<Object, Object>> entrySet = pro.entrySet();
        for (Map.Entry<Object, Object> entry : entrySet) {
            map.put((String) entry.getKey(), (String) entry.getValue());
        }
        return map;
    }
}

4. 配置redis

如:redis key是config_center:prod:testdemo

spring.application.name=testdemo-server
server.port=15550
conf-ref=eureka-client,dao,spring-boot,redis,druid

上面的配置中conf-ref代码,我还要引入外部的配置,那么配置中还有config_center:prod:druid,config_center:prod:dao这些配置key。分类配置,清晰明了如图:

5. 客户端配置

客户端我们需要获取到配置中心的配置信息。那我们只需要在配置中标明config的IP端口即可。

#Config配置服务
spring.cloud.config.profile=manager
spring.cloud.config.name=application
spring.cloud.config.label=prod
spring.config.import=optional:configserver:http://127.0.0.1:10051

​​​​​​​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大猩猩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值