【p4】配置中心代码实现

(转载请注明作者和出处‘https://fourthringroad.com/’,请勿用于任何商业用途)

ooooookay, 整理一下P1-P3里的内容,把它精简成以下需求:

  1. 我有一个配置中心服务,托管用户配置信息。
  2. 用户能够用一个注解,将配置信息同步到应用运行时内存的配置bean
  3. 当配置中心的配置修改发生时,自动将新的配置同步到相关bean

很简单,来写个demo。

客户端

首先是注解的设计,前面已经讲过了,不赘述:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigAnnotation {

    //配置的ID
    String value();

    enum Format {XML, JSON, YML, PROPERTIES}

    //配置文件的类型
    Format format() default Format.PROPERTIES;
}

然后是如何获取配置,以及如何解析配置:

获取配置内容的client,先提供client的抽象

public interface ConfigClient {
    String getConfig(String configId);
}

如何解析配置的相关类,这里提供了Properties文件解析器,其实就是转化为一个string-string的键值map

/**
 * 解析配置文件.
 * 出于demo目的,这里只提供将其转化为Map的接口,用于支持K-V配置的解析,例如java Properties文件解析.
 */
public interface Resolver {
    Map<String, String> resolve(String config);
}
public class ResolverFactory {

    private static final Map<Format, Resolver> resolvers = new ConcurrentHashMap<>();

    public static Resolver getResolver(Format format) {
        switch (format) {
            case XML:
                //TBD
                break;
            case JSON:
                //TBD
                break;
            case YML:
                //TBD
                break;
            case PROPERTIES:
                resolvers.putIfAbsent(Format.PROPERTIES, new PropertiesResolver());
                return resolvers.get(Format.PROPERTIES);
        }
        throw new IllegalStateException("不支持这种格式: " + format);
    }

    public static class PropertiesResolver implements Resolver {
        @Override
        public Map<String, String> resolve(String config) {

            final Properties properties = new Properties();
            try {
                properties.load(new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8)));
            } catch (IOException e) {
                throw new IllegalStateException("不能解析Config");
            }
            return (Map) properties;
        }
    }
}

然后是最重要的一步,介入bean的生命周期,给bean赋值并动态更新

可以看到从两个地方介入了bean的构建过程:

首先是postProcessProperties,对bean的初值进行了赋予,从ConfigManager获得配置信息,解析,然后给bean赋值使用

接着是postProcessAfterInitialization,在bean初始化完成之后,注册到ConfigManager,后者用观察者模式,当检测到配置修改后,相应的也会更新bean实例的属性。

@Component
public class ConfigAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    private final ConfigManager configManager;

    public ConfigAnnotationBeanPostProcessor(ConfigManager configManager) {
        this.configManager = configManager;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

        final Class<?> cls = bean.getClass();

        if (cls.isAnnotationPresent(ConfigAnnotation.class)) {
            final ConfigAnnotation configAnnotation = cls.getAnnotation(ConfigAnnotation.class);

            final String config = configManager.getConfig(configAnnotation.value());
            final Map<String, String> resolvedProperties = ResolverFactory.getResolver(configAnnotation.format())
                    .resolve(config);

            //简便起见,不考虑父类的属性
            final Field[] fields = cls.getDeclaredFields();
            final MutablePropertyValues mutablePropertyValues = new MutablePropertyValues(pvs);
            for (Field field : fields) {
                final String fieldName = field.getName();
                final String fieldValue = resolvedProperties.get(fieldName);
                if (fieldValue != null) {
                    mutablePropertyValues.add(fieldName, fieldValue);
                }
            }
            return mutablePropertyValues;
        }

        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        final Class<?> cls = bean.getClass();
        if (cls.isAnnotationPresent(ConfigAnnotation.class)) {
            final ConfigAnnotation configAnnotation = cls.getAnnotation(ConfigAnnotation.class);
            configManager.register(configAnnotation.value(), bean, configAnnotation.format());
        }
        return bean;
    }

这里提到的ConfigManager其实功能就是上面两个:周期性的调用ConfigClient的接口去获取配置,保证内存cache中是最新的配置;当检测到配置修改后,修改对应bean中的属性。

/**
 * delegate ConfigClient 来更新内存中的配置
 * 当配置发生改变时通知对应的实例
 */
@Component
public class ConfigManager {

    private final ConfigClient configClient;

    private final Map<String, String> cache = new ConcurrentHashMap<>();

    private final Map<String, Map.Entry<Object, Format>> observers = new ConcurrentHashMap<>();

    public ConfigManager(ConfigClient configClient) {
        this.configClient = configClient;

        final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
            try {
                cache.forEach(
                        (configId, oldConfig) -> {
                            final String newConfig = configClient.getConfig(configId);
                            if (!oldConfig.equals(newConfig)) {
                                cache.put(configId, newConfig);
                                notifyObserver(configId, newConfig);
                            }
                        });
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    public String getConfig(final String configId) {
        if (cache.containsKey(configId)) {
            return cache.get(configId);
        } else {
            final String config = configClient.getConfig(configId);
            cache.put(configId, config);
            return config;
        }
    }

    public void register(final String configId, final Object bean, final Format format) {
        observers.put(configId, new AbstractMap.SimpleEntry<Object, Format>(bean, format));
    }

    private void notifyObserver(String configId, String config) {
        if (observers.containsKey(configId)) {
            Object bean = observers.get(configId).getKey();
            Format format = observers.get(configId).getValue();
            final Map<String, String> resolvedProperties = ResolverFactory.getResolver(format).resolve(config);
            final Class<?> cls = bean.getClass();
            final Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                final String fieldName = field.getName();
                final String fieldValue = resolvedProperties.get(fieldName);
                if (fieldValue != null) {
                    try {
                        field.set(bean, fieldValue);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                field.setAccessible(false);
            }
        }
    }
}

最后给我们的工具包增加一个对外输出的配置文件

因为没有搭建真的服务,所有在这里ConfigClient提供了一个stub实现,每调用5次接口,就会切换到一个不同响应配置文件,来模拟配置文件改动的情况。

@Configuration
@ComponentScan("com.sihuan.prototype")
public class ConfigClientConfiguration {

    @Bean
    public ConfigClient configClient() {
        return new StubConfigClient();
    }

    /**
     * 出于测试目的,这里提供一个stub来提供ConfigClient的功能
     */
    public static class StubConfigClient implements ConfigClient {
        private final AtomicInteger counter = new AtomicInteger();

        @Override
        public String getConfig(String configId) {
            if ("testConfig".equals(configId)) {
                return counter.addAndGet(1) / 5 % 2 == 0 ?
                        "name=bob\n" +
                                "job=developer\n" +
                                "company=google\n" +
                                "salary=99999" :
                        "name=jack\n" +
                                "job=sales\n" +
                                "company=apple\n" +
                                "salary=88888";
            }
            throw new RuntimeException();
        }
    }
}

OK,完成之后用户就可以使用了。

用户应用使用

直接定义一个bean,并用上我们的注解

/**
 * 真实情况fields不会都是String,出于演示目的,这里简化了复杂类型转换的场景
 */
@Component
@ConfigAnnotation(value = "testConfig", format = ConfigAnnotation.Format.PROPERTIES)
public class ConfigBean {
    private String name;
    private String job;
    private String company;
    private String salary;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getSalary() {
        return salary;
    }

    public void setSalary(String salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "ConfigBean{" +
                "name='" + name + '\'' +
                ", job='" + job + '\'' +
                ", company='" + company + '\'' +
                ", salary='" + salary + '\'' +
                '}';
    }
}

写个main函数来测试:

public class App {
    public static void main(String[] args) throws InterruptedException {
        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CustomerConfiguration.class);

        final ConfigBean configBean = (ConfigBean) context.getBean("configBean");

        while (true) {
            TimeUnit.SECONDS.sleep(1);
            System.out.println(configBean);
        }
    }

    @Configuration
    @Import(ConfigClientConfiguration.class)
    @ComponentScan(value = "org.test")
    public static class CustomerConfiguration {
    }
}

打印结果为:

ConfigBean{name='bob', job='developer', company='google', salary='99999'}
ConfigBean{name='bob', job='developer', company='google', salary='99999'}
ConfigBean{name='bob', job='developer', company='google', salary='99999'}
ConfigBean{name='jack', job='sales', company='apple', salary='88888'}
ConfigBean{name='jack', job='sales', company='apple', salary='88888'}
ConfigBean{name='jack', job='sales', company='apple', salary='88888'}
ConfigBean{name='jack', job='sales', company='apple', salary='88888'}
ConfigBean{name='jack', job='sales', company='apple', salary='88888'}
ConfigBean{name='bob', job='developer', company='google', salary='99999'}
ConfigBean{name='bob', job='developer', company='google', salary='99999'}
ConfigBean{name='bob', job='developer', company='google', salary='99999'}
.......

OK,仅仅通过一个注解帮助我们的客户获取了配置,映射到自定义类中,并且可以实现实时的更新。这个实现方案没有考虑性能和很多细节,真实的方案比这个复杂很多,但是也就意味着,在真正的方案中会给用户节省更多的重复开发,降低onboard难度。

此条目发表在spring相关分类目录。将固定链接加入收藏夹。

【p4】配置中心代码实现》有137条回应

  1. Descubre la inspiradora trayectoria de Sergio Ramos en el futbol | Explora las estadisticas y rendimiento de Ramos en EA FC 24 | Explora el impacto de Ramos en el PSG y sus contribuciones | Informate sobre los records de Ramos en La Liga y Europa | Descubre el viaje de Ramos desde Sevilla hasta los grandes clubes | Explora los anos dorados de Ramos en el Real Madrid | Informate sobre el salario y las ganancias de Ramos | Informate sobre el perfil completo de Ramos en EA FC | Explora las contribuciones de Ramos al mundo del futbol, historia de Sergio Ramos Historia de Sergio Ramos.

  2. mostbetatPa说:

    Погрузитесь в мир ставок и азартных игр с Мостбет | Играйте на Мостбет и получайте бонусы за регистрацию | Регистрируйтесь и начните зарабатывать с Мостбет | С Мостбет вы всегда сможете найти рабочее зеркало | Зарегистрируйтесь на Мостбет и получите бонус на ставки | Ставки и игры с надёжным сервисом – только на Мостбет | Популярное казино для игроков Казахстана – Мостбет | Играйте в слоты и выигрывайте реальные деньги на Мостбет | Установите приложение и получите бонус на Мостбет, скачать Mostbet Mostbet скачать на андроид.

  3. Lee sobre el impacto de Pogba en el Juventus | Informate sobre la vida personal y profesional de Pogba | Informate sobre la vida familiar de Pogba | Conoce mas sobre la vida de Pogba con su familia | Descubre como Pogba ha influenciado a jovenes futbolistas | Descubre los logros de Pogba en la seleccion nacional | Explora el impacto de Pogba en el futbol mundial | Descubre el impacto de Pogba en la liga de Italia | Lee sobre el talento futbolistico de Paul Pogba, datos de Pogba https://pogba-es.org.

  4. mostbetqbPa说:

    Присоединяйтесь к Мостбет и выигрывайте реальные деньги | Обновлённый интерфейс и удобная навигация в Мостбет | Получите лучшие шансы и высокие коэффициенты на Мостбет | Простая регистрация на Мостбет с бонусом за первое пополнение | Большой выбор игр для каждого игрока на Мостбет | Проверьте свои шансы в слотах Мостбет | Пользуйтесь всеми функциями мобильного приложения Мостбет | Мостбет – это ваш путь к крупным выигрышам | Ставки и казино в одном месте – это Мостбет, Мостбет слоты слоты Мостбет.

  5. Descubre como Ronaldinho inspiro a una generacion de futbolistas | Explora la conexion de Ronaldinho con los jovenes futbolistas | Conoce el estilo unico y el talento de Ronaldinho | Descubre las curiosidades de la vida de Ronaldinho | Conoce los exitos y premios de Ronaldinho en su carrera | Descubre el camino de Ronaldinho a la fama mundial | Explora la influencia de Ronaldinho en el futbol actual | Descubre las contribuciones de Ronaldinho al futbol global | Descubre los detalles de la carrera profesional de Ronaldinho, Ronaldinho historia Historia Ronaldinho.

  6. vinijrnfPa说:

    Conoce la historia de superacion de Vinicius Junior | Informate sobre la posicion y estilo de juego de Vinicius | Conoce la historia de Vinicius antes de unirse al Real Madrid | Conoce el perfil completo de Vini Jr. en Transfermarkt | Explora el talento y futuro de Vini en el futbol | Conoce el perfil completo de Vinicius en Transfermarkt | Descubre como la familia de Vinicius influyo en su exito | Explora la biografia completa de Vinicius Junior | Conoce la habilidad y estilo unicos de Vini en el campo, perfil completo de Vinicius https://vinicius-junior-es.org.

  7. marcelogdPa说:

    Conoce los datos personales y curiosidades de Marcelo Vieira | Conoce la vida familiar y personal de Marcelo fuera del campo | Descubre la historia de Marcelo y su papel en el Real Madrid | Conoce el viaje de Marcelo a traves de los clubes en los que jugo | Informate sobre el estilo de juego y habilidades de Marcelo | Explora los mejores partidos de Marcelo en su carrera | Explora la personalidad y carisma de Marcelo en el futbol | Informate sobre el apoyo y motivacion de Marcelo a sus companeros | Descubre los momentos inolvidables de Marcelo en el futbol, edad de Marcelo Edad de Marcelo</url].

  8. Оформляйте онлайн-заказы на ставку в любое время | Получите рекомендации по ставкам от экспертов Mostbet | Откройте новые возможности для ставок с Мостбет | Доступен широкий ассортимент игр в онлайн-казино Mostbet | Оформите первую ставку и получите бонус на Mostbet | Mostbet – это честные условия и быстрые выплаты | Узнайте все о ставках и игре в Мостбет | Лояльная программа для всех игроков на Mostbet | Используйте удобный интерфейс на сайте Mostbet http://www.mostbetkzcasino.com.kz.

  9. HermanAvecy说:

    условия проведения соут https://sout095.ru

  10. HermanAvecy说:

    особенности проведения соут аккредитация соут

  11. Profitez des paris en direct avec Mostbet en un seul clic | Profitez des jeux de hasard et des paris sportifs avec Mostbet | Telechargez l’application pour des paris instantanes mostbet casino mostbet casino.

  12. Entre agora no site oficial Mostbet e descubra promocoes exclusivas | Descubra as melhores odds no site de apostas Mostbet | Use o aplicativo Mostbet para apostas rapidas e convenientes | Conheca a emocao do jogo Aviator no Mostbet | Experimente o cassino ao vivo do Mostbet e interaja com dealers reais | Aposte nos seus esportes favoritos com odds elevadas no Mostbet | Explore o Mostbet Brasil e descubra uma plataforma completa | Descubra o jogo Aviator e ganhe premios instantaneos no Mostbet | Descubra promocoes e bonus diarios no site Mostbet Brasil site mostbet site mostbet.

  13. Загрузите мобильное приложение Мостбет и играйте где угодно | Зеркало Мостбет поможет вам войти в аккаунт без ограничений | Погрузитесь в азарт с казино Mostbet | Ставки на спорт с Мостбет — это ваш шанс на победу | Наслаждайтесь лучшими играми и бонусами на Мостбет Украина | Скачайте приложение Мостбет и наслаждайтесь игрой | Скачайте Mostbet и испытайте удачу в любой момент | Получите бесплатную ставку при регистрации на Мостбет | Попробуйте удачу на Мостбет и получите бонус за регистрацию Мостбет официальный сайт

  14. Випробуйте своє везіння на Mostbet і отримайте бездепозитний бонус | Легко і зручно – ставки на Mostbet | Скачайте Mostbet і насолоджуйтесь грою будь-де | Офіційний сайт Mostbet – вибір переможців | Грайте в Mostbet та отримуйте щедрі бонуси mostbet casino

  15. Mostbet O‘zbekistonda eng yaxshi o‘yin tanlovlarini taklif etadi | Mostbet sayti orqali yangi yutuqlar uchun imkoniyat yarating | Mostbet bilan o‘yinlar va pul tikish uchun qulaylik va tezkor to‘lovlar | Mostbet onlayn kazino va sport turlari uchun eng yaxshi joy | Mostbet bilan o‘yinlar va pul tikish uchun qulaylik va tezkor to‘lovlar http://mostbetazcasino.com.az/

  16. Мостбет казино – все, що потрібно для азартної гри | Грайте та вигравайте на mostbet без обмежень | Насолоджуйтесь якісним сервісом та високими виграшами на mostbet | Легке завантаження додатку mostbet для Android та iOS | Мостбет пропонує найкращі слоти для азартних ігор most bet casino

  17. Mostbet – найкращий вибір для ставок в Україні | Завантажте mostbet та грайте без обмежень | Насолоджуйтесь азартом на mostbet UA | Отримуйте великий виграш на мостбет казино | Швидка реєстрація на офіційному сайті mostbet http://www.mostbet-ua-casino.kiev.ua

  18. Mostbet-da o‘yin o‘ynash imkoniyati har doim mavjud | Mostbet sayti orqali yangi yutuqlar uchun imkoniyat yarating | Mostbet orqali har kuni yangi aksiyalar va bonuslar | Mostbet-ning rasmiy saytiga har doim kirish imkoniyati mavjud | Mostbet-da yangi o‘yinlarni sinab ko‘ring va katta yutuqlar qo‘lga kiriting aviator mostbet

  19. brotapova说:

    Milford qgZIAHflmJeSW 6 17 2022 priligy dosage

  20. brotapova说:

    Ongoing and finalized clinical trials are summarized in Tables 2 and 3 where to buy priligy in malaysia

  21. Mostbet offers exciting sports betting options | Discover the best odds with Mostbet online | Mostbet app offers secure and smooth navigation | Mostbet login gives you access to endless gaming options | Play responsibly with Mostbet Bangladesh | Bet on international sports with Mostbet Bangladesh Mostbet registration.

  22. Register on Mostbet and get a welcome bonus | Discover the best odds with Mostbet online | Bet anytime, anywhere with the Mostbet app | Mostbet login gives you access to endless gaming options | Mostbet Bangladesh is your trusted betting partner | Experience seamless gaming on the Mostbet platform https://mostbetbdbangladesh.com.

  23. Enjoy seamless betting on Mostbet in Bangladesh | Mostbet registration is quick and simple | Mostbet app delivers the ultimate betting experience | Mostbet promo codes unlock extra bonuses for players | Enjoy 24/7 customer support on Mostbet Bangladesh | Play and win on Mostbet’s live casino platform | Mostbet casino is trusted by players worldwide Mostbet casino.

  24. Mostbet provides fast registration and instant rewards | Mostbet app provides all-in-one solutions for gaming | Explore secure and convenient gaming on Mostbet | Explore Mostbet’s diverse casino game selection | Mostbet’s Aviator game is a favorite among players | Mostbet is the best platform for online betting | Secure your winnings with Mostbet’s trusted platform Mostbet casino.

  25. Mostbet az oyunçular üçün xüsusi təkliflər təqdim edir | Mostbet tətbiqi ilə hər zaman mərc edin | Mostbet oyunçular üçün unikal təcrübə təqdim edir | Mostbet tətbiqini yükləyərək hər yerdə mərc edin | Mostbet tətbiqi ilə hər yerdən oyunlara qoşulun | Mostbet ilə böyük bonuslar əldə edin | Mostbet Azərbaycan oyunçuları üçün xüsusi bonuslar təklif edir | Mostbet tətbiqi ilə hər zaman oynamaq rahatdır | Mostbet az ilə hər zaman yüksək əmsallardan istifadə edin Mostbet bonusları.

  26. Mostbet qeydiyyatı ilə bonuslar qazanın | Mostbet oyunçulara 24/7 dəstək xidmətləri təklif edir | Mostbet Azərbaycan üçün ən yaxşı seçimdir | Mostbet ilə böyük məbləğdə uduşlar qazanın | Mostbet az oyunçular üçün əlverişli şərtlər təqdim edir | Mostbet qeydiyyatı prosesi çox sürətlidir | Mostbet ilə hər zaman qalib gəlmək mümkündür | Mostbet ilə risksiz mərc edin və qazanmağa başlayın | Mostbet az ilə hər zaman yüksək əmsallardan istifadə edin http://www.mostbet-online-az-qeydiyyat.com.

  27. Mostbet Azərbaycanda ən etibarlı mərc platformasıdır | Mostbet ilə sürətli və təhlükəsiz ödənişlər həyata keçirin | Mostbet az tətbiqi istifadə etmək çox rahatdır | Mostbet azərbaycanlı oyunçuların ən sevimli platformasıdır | Mostbet tətbiqi ilə hər yerdən oyunlara qoşulun | Mostbet az ilə təhlükəsiz mərc etmək mümkündür | Mostbet Azərbaycan oyunçuları üçün xüsusi bonuslar təklif edir | Mostbet oyun dünyasında liderdir və ən yaxşı xidmətləri təqdim edir | Mostbet ilə təhlükəsiz mərc təcrübəsi əldə edin Mostbet casino.

  28. Неотразимый стиль современных тактичных штанов, как носить их с другой одеждой.
    Неотъемлемая часть гардероба – тактичные штаны, которые подчеркнут ваш стиль и индивидуальность.
    Идеальные тактичные штаны: находка для занятых людей, который подчеркнет вашу уверенность и статус.
    Лучшие модели тактичных штанов для мужчин, которые подчеркнут вашу спортивную натуру.
    Советы по выбору тактичных штанов для мужчин, чтобы подчеркнуть свою уникальность и индивидуальность.
    Тактичные штаны: вечная классика мужского гардероба, которые подчеркнут ваш вкус и качество вашей одежды.
    Лучший вариант для делового образа: тактичные штаны, которые подчеркнут ваш профессионализм и серьезность.
    купити штани тактичні купити штани тактичні .

  29. Hubertned说:

    Reliable HVAC Repair Services https://serviceorangecounty.com stay comfortable year-round with our professional HVAC repair services. Our experienced team is dedicated to diagnosing and resolving heating, cooling, and ventilation issues quickly and effectively.

  30. Jamesedusy说:

    РПНУ Лизинг https://rpnu-leasing.ru надежный партнер в лизинге автомобилей, спецтехники и оборудования. Гарантируем отсутствие отказов благодаря индивидуальному подходу к каждому клиенту. Удобные условия и быстрое оформление помогают получить нужное имущество без лишних сложностей.

  31. LorenzoJeart说:

    Plinko se ha convertido https://medium.com/@kostumchik.kiev.ua/todo-sobre-el-juego-de-plinko-en-m%C3%A9xico-instrucciones-demos-opiniones-y-m%C3%A1s-d1fde2d99338 en una de las opciones favoritas de los jugadores de casinos en Mexico. Conocido por su simplicidad y gran potencial de ganancias, este adictivo juego ahora cuenta con una plataforma oficial en Mexico.

  32. Dennisspoff说:

    Онлайн-журнал о строительстве https://zip.org.ua практичные советы, современные технологии, тренды дизайна и архитектуры. Всё о строительных материалах, ремонте, благоустройстве и инновациях в одной удобной платформе.

  33. Frankvom说:

    Рейтинг лучших онлайн-казино https://lastdepcasino.ru с быстрыми выплатами и честной игрой. Подробные обзоры, бонусы для новых игроков и актуальные акции.

  34. RichardWer说:

    Ваш гид в мире автомобилей https://clothes-outletstore.com тест-драйвы, советы по ремонту и последние тенденции индустрии.

  35. Larryhoave说:

    Автомобильный журнал https://automobile.kyiv.ua с фокусом на практичность. Ремонт, уход за авто, обзор технологий и советы по эксплуатации.

  36. Danielperve说:

    Всё о машинах https://avtomobilist.kyiv.ua тест-драйвы, сравнения моделей, авто новости, советы по ремонту и уходу.

  37. Aaronaccup说:

    Авто журнал https://avtonews.kyiv.ua новости автопрома, сравнения моделей, тест-драйвы, советы по ремонту и уходу.

  38. Scottdroff说:

    Авто портал https://autonovosti.kyiv.ua актуальные новости, обзоры авто, тест-драйвы, инструкции по ремонту и тюнингу. Минимум текста, максимум полезной информации.

  39. WilliamApozy说:

    Всё о машинах https://black-star.com.ua авто новости, тест-драйвы, обзоры моделей, рейтинги, инструкции по обслуживанию и ремонту.

  40. Ronaldglome说:

    Всё о самогоноварении https://brewsugar.ru на одном сайте: от истории напитка до современных технологий перегонки.

  41. DennisVog说:

    Всё об авто https://road.kyiv.ua в одном месте: новости, тест-драйвы, сравнения, характеристики, ремонт и уход. Автомобильный онлайн-журнал — ваш эксперт в мире машин.

  42. Michaelfeete说:

    Место для общения на любые темы https://xn--9i1b12ab68a.com/ актуальные вопросы, обмен опытом, интересные дискуссии. Здесь найдётся тема для каждого.

  43. TommyIsomo说:

    Перевозка товаров из Китая https://chinaex.ru в Россию под ключ: авиа, море, автотранспорт. Гарантия сроков и сохранности груза.

  44. Frankdah说:

    Женский портал https://abuki.info мода, красота, здоровье, семья, карьера. Советы, тренды, лайфхаки, рецепты и всё, что важно для современных женщин.

  45. MilesWap说:

    Автомобильный онлайн-журнал https://simpsonsua.com.ua предлагает свежие новости, обзоры авто, тест-драйвы, рейтинги и полезные советы для водителей.

  46. Domingoliz说:

    Мода, здоровье, красота https://gratransymas.com семья, кулинария, карьера. Женский портал — полезные советы и свежие идеи для каждой.

  47. GregoryfrepT说:

    Познавательный портал для детей https://detiwki.com.ua обучающие материалы, интересные факты, научные эксперименты, игры и задания для развития кругозора.

  48. AnthonySal说:

    Женский онлайн-журнал https://womanfashion.com.ua секреты красоты, модные тренды, здоровье, отношения, семья, кулинария и карьера. Всё, что важно и интересно.

  49. JeffreyUnpak说:

    Discover the latest game codes https://pocket-codes.com detailed guides, and expertly crafted tier lists to enhance your gaming experience. Unlock rewards, master strategies, and dominate every level with our curated content. Perfect for gamers seeking an edge!

  50. EverettCoany说:

    Женский онлайн-журнал https://stylewoman.kyiv.ua стиль, уход, здоровье, отношения, семья, кулинарные рецепты, психология и карьера.

  51. Joshuaket说:

    Туристический портал https://aliana.com.ua лучшие маршруты, путеводители, советы путешественникам, обзоры отелей.

  52. Rudolphpug说:

    элитная офисная мебель для руководителя офисная мебель для персонала купить

  53. Edwardtit说:

    Всё о туризме https://atrium.if.ua маршруты, путеводители, советы по отдыху, обзор отелей и лайфхаки. Туристический портал — ваш помощник в путешествиях.

  54. WilliamGab说:

    Всё для путешествий https://cmc.com.ua уникальные маршруты, гиды по городам, актуальные акции на туры и полезные статьи для туристов.

  55. WilliamDeamp说:

    Статьи о путешествиях https://deluxtour.com.ua гиды по направлениям, лайфхаки для отдыха, советы по сбору багажа и туристические обзоры.

  56. GregoryFeero说:

    Путешествия по Греции https://cpcfpu.org.ua лучшие курорты, гиды по островам, экскурсии, пляжи и советы по планированию отпуска.

  57. DennisWam说:

    Туристический журнал https://elnik.kiev.ua свежие идеи для путешествий, обзоры курортов, гиды по городам, советы для самостоятельных поездок и туристические новости.

  58. Stevennus说:

    Туристический портал https://feokurort.com.ua необычные маршруты, вдохновляющие истории, секреты бюджетных путешествий, советы по визам и топовые направления для отдыха.

  59. JosephCouct说:

    Статьи о туризме и путешествиях https://inhotel.com.ua маршруты, гиды по достопримечательностям, советы по планированию поездок, рекомендации по отелям и лайфхаки для туристов.

  60. WilliamWek说:

    Гиды по странам https://hotel-atlantika.com.ua экскурсии по городам, советы по выбору жилья и маршрутов. Туристический журнал — всё для комфортного и яркого путешествия.

  61. PabloMaymn说:

    Комплексный ремонт квартир https://anti-orange.com.ua и домов от Студии ремонта. Полный цикл работ: от дизайна до финишной отделки.

  62. Phillipbeerb说:

    Строительная компания https://as-el.com.ua выполняем строительство жилых и коммерческих объектов под ключ. Полный цикл: проектирование, согласование, строительство и отделка.

  63. BobbyKaw说:

    На строительном портале https://avian.org.ua вы найдете всё: от пошаговых инструкций до списка лучших подрядчиков. Помогаем реализовать проекты любой сложности быстро и удобно.

  64. NathanSmene说:

    Строительный портал https://ateku.org.ua ваш гид в мире строительства и ремонта. Полезные статьи, обзоры материалов, советы по выбору подрядчиков и идеи дизайна.

  65. HarryAdone说:

    Портал по ремонту https://azst.com.ua всё для вашего ремонта: подбор подрядчиков, советы по выбору материалов, готовые решения для интерьера и проверенные рекомендации.

  66. Velas_lwer说:

    Настроение в вашем доме с помощью ароматических свечей, Вдохновляющие ароматы для вашего дома, Какие ароматы велас свечей подходят для спальни
    catalogo velas catalogo velas .

  67. Henrypaf说:

    Всё о ремонте на одном сайте https://comart.com.ua Портал по ремонту предлагает обзоры материалов, рейтинги специалистов, советы экспертов и примеры готовых проектов для вдохновения.

  68. ElmerHoilk说:

    Журнал по ремонту https://domtut.com.ua и строительству – советы, идеи и обзоры. Узнайте о трендах, изучите технологии и воплотите свои строительные или дизайнерские задумки легко и эффективно.

  69. Eduardomagma说:

    Портал о ремонте https://eeu-a.kiev.ua всё для тех, кто ремонтирует: пошаговые инструкции, идеи дизайна, обзор материалов и подбор подрядчиков.

  70. Williamthymn说:

    Журнал по ремонту и строительству https://diasoft.kiev.ua гид по современным тенденциям. Полезные статьи, лайфхаки, инструкции и обзор решений для дома и офиса.

  71. Jamesded说:

    Новости технологий https://helikon.com.ua все о последних IT-разработках, гаджетах и научных открытиях. Свежие обзоры, аналитика и тренды высоких технологий.

  72. Donaldved说:

    порядок проведения оценки профессиональных рисков Москва оценка профессиональных рисков по охране труда цена в Москве

  73. ScottNub说:

    Строительный онлайн журнал https://inter-biz.com.ua руководства по проектам любой сложности. Советы экспертов, подбор материалов, идеи дизайна и новинки рынка.

  74. RobertoBax说:

    Строительные технологии https://ibss.org.ua новейшие разработки и решения в строительной сфере. Материалы, оборудование, инновации и тренды для профессионалов и застройщиков.

  75. EdmundAwaiz说:

    Сайт о строительстве и ремонте https://hydromech.kiev.ua полезные советы, инструкции, обзоры материалов и технологий. Все этапы: от фундамента до отделки.

  76. Craigmox说:

    Все о строительстве и ремонте https://kennan.kiev.ua практичные рекомендации, идеи интерьеров, новинки рынка и советы профессионалов.

  77. Danielhek说:

    Дизайн интерьера и территории https://lbook.com.ua идеи оформления жилых и коммерческих пространств. Современные тренды, советы экспертов и решения для создания стильного и функционального пространства.

  78. CharlesViods说:

    Асфальтирование и ремонт дорог https://mia.km.ua информация о технологиях укладки асфальта, методах ремонта покрытий и современных материалах.

  79. LloydBex说:

    Kompaktni zarizeni mikrosluchatka poskytuje spolehlivy prenos, pevny, nenapadny design a pohodlne se nosi v kazde situaci.

  80. Jamesnat说:

    Онлайн-журнал о строительстве https://mts-slil.info свежие новости, обзоры инноваций, рекомендации по ремонту и строительству.

  81. Davidrig说:

    Сайт про ремонт https://odessajs.org.ua полезные советы, инструкции, подбор материалов и идеи дизайна. Всё, что нужно для качественного и продуманного ремонта любого помещения.

  82. Brianswige说:

    Мастерская креативных идей https://rusproekt.org пространство для творчества и инноваций. Уникальные решения для дизайна, декора и проектов любого масштаба.

  83. BillyEvops说:

    Онлайн журнал о ремонте https://prezent-house.com.ua статьи, лайфхаки и решения для всех этапов ремонта: от планирования до отделки. Практичные рекомендации и идеи для вашего дома.

  84. Ronaldanymn说:

    Журнал о строительстве и ремонте https://selma.com.ua советы экспертов, обзор материалов, тренды в интерьере и готовые решения для качественного ремонта вашего дома или офиса.

  85. Davidpop说:

    Портал о ремонте https://rvps.kiev.ua практичные рекомендации, дизайн-идеи, современные технологии и инструкции для успешного ремонта любого уровня сложно

  86. JasperStany说:

    Сайт о дизайне интерьера и территории https://sinega.com.ua тренды в дизайне помещений и благоустройстве территорий.

  87. JulesCem说:

    Информационный портал о ремонте https://sevgr.org.ua практичные советы, проверенные методики и новинки рынка. Помощь в планировании, выборе подрядчиков и создании идеального пространства.

  88. Kevinflese说:

    Портал об архитектуре https://solution-ltd.com.ua информация о культовых проектах, новые технологии строительства, эстетика пространств и актуальные решения для городов и частных

  89. MathewFoolo说:

    Архитектурный портал https://skol.if.ua новости архитектуры, современные проекты, градостроительные решения и обзоры мировых трендов.

  90. JosephVeirm说:

    Информационный портал о ремонте https://stinol.com.ua практичные советы, проверенные методики и новинки рынка. Помощь в планировании, выборе подрядчиков и создании идеального пространства.

  91. Josephoccaw说:

    Гид по ремонту https://techproduct.com.ua идеи и советы для самостоятельного ремонта: экономичные решения, готовые проекты, обзоры материалов и дизайнерские лайфхаки.

  92. Parkerstisy说:

    Журнал про строительство и ремонт https://ukrainianpages.com.ua профессиональные статьи о ремонте любой сложности. Как оптимизировать расходы, найти подрядчиков и добиться идеального результата.

  93. Marionnew说:

    Find the best https://onlinecasinocanada.shop offers! Explore top-rated casinos with free spins and bonus cash for new players. Start playing without risking your funds.

  94. Josephfrini说:

    Автодоставка из Китая https://china-top.ru быстрая и надежная транспортировка товаров. Полный цикл: от оформления документов до доставки на склад клиента.

  95. DavidAbuts说:

    Смотреть индийские фильмы онлайн https://kinoindia.tv подборка лучших фильмов с уникальным колоритом. Бесплатный доступ и ежедневное обновление каталога.

  96. MiguelFounk说:

    Журнал про строительство и ремонт https://ukrainianpages.com.ua профессиональные статьи о ремонте любой сложности. Как оптимизировать расходы, найти подрядчиков и добиться идеального результата.

  97. Marcusfaw说:

    Назальный спрей Серебряный Углерон надежная защита вашего дыхания. Активный углерод и ионы серебра очищают носовые ходы, увлажняют слизистую и помогают бороться с бактериями.

  98. Ronniesiz说:

    Free Online Games playgama your gateway to a world of free online entertainment! Explore a vast collection of games, from puzzles and card games to action and arcade classics. Play instantly on any device without registration or downloads

  99. Stephenduh说:

    шары с доставкой недорого шары за час доставка

  100. Jamesitemo说:

    Техосмотр в Санкт-Петербурге! грузовой техосмотр

  101. LeroyOrids说:

    Летайте выгодно с Pegasus Airlines предлагаем доступные билеты, удобные маршруты и современный сервис. Внутренние и международные рейсы для комфортных путешествий.

  102. Peterneush说:

    Оценка профессиональных рисков https://ocenka-riskov-msk.ru комплексная услуга для выявления, анализа и снижения угроз на рабочем месте.

  103. Richardunjus说:

    Наши бюстгальтер женский предлагают идеальное сочетание стиля и комфорта. Выберите бюстгальтер без косточек для мягкой поддержки или кружевной бюстгальтер для романтичного образа. Для будущих мам подойдут бюстгальтеры для беременных и бюстгальтеры для кормления. Обратите внимание на бюстгальтер с пуш-ап для эффекта увеличения груди и комфортные бюстгальтеры для повседневного ношения.

  104. Myronsed说:

    Предлагаем стекла для спецтехники https://steklo-ufa.ru любых типов и размеров. Прочные, устойчивые к ударам и погодным условиям материалы.

  105. Kellymal说:

    Производство шпона в Москве https://shpon-massiv.ru качественный шпон из натурального дерева для мебели, дверей и отделки. Широкий выбор пород, гибкие размеры и выгодные цены.

  106. DavidTip说:

    Инженерные изыскания в Москве https://geology-kaluga.ru точные исследования для строительства и проектирования. Геологические, гидрологические, экологические и геодезические работы для строительства.

  107. TimothyRox说:

    Геосинтетические материалы https://geobentomat.ru надежное решение для строительства и укрепления грунтов. Геотекстиль, георешетки, геомембраны и другие материалы для дренажа, армирования и защиты конструкций.

  108. Thomastal说:

    Torlab.net https://torlab.net новый торрент-трекер для поиска и обмена файлами! Здесь вы найдете фильмы, игры, музыку, софт и многое другое. Быстрая скорость загрузки, удобный интерфейс и активное сообщество. Подключайтесь, делитесь, скачивайте — ваш доступ к миру качественного контента!

  109. KelvinTebra说:

    Доставка дизельного топлива https://neftegazlogistic.ru в Москве – оперативно и качественно! Поставляем ДТ для автотранспорта, строительной и спецтехники. Гарантия чистоты топлива, выгодные цены и быстрая доставка прямо на объект.

  110. HenryGrelp说:

    https://rxguides.net/guides Explore detailed guides to master your favorite games. From beginner tips to advanced strategies, our guides help you level up, complete challenges, and unlock hidden secrets for the ultimate gaming experience.

  111. onexbet_gion说:

    Получайте больше прибыли на onexbet, не отрываясь от компьютера.
    onexbet – ваш шанс на богатство, где бы вы ни находились.
    Ставки на спорт с onexbet, самые выгодные коэффициенты.
    Попробуйте свою удачу вместе с onexbet, и у вас не будет никаких сожалений.
    onexbet – качество и профессионализм, всегда гарантированы.
    Готовы ли вы к большим выигрышам? Вам нужен onexbet, – оптимальное решение в вашей ситуации.
    onexbet – ваш надежный союзник в мире игры, на который всегда можно положиться.
    Onexbet – ваш путь к вершине, добивайтесь успеха вместе с onexbet.
    onexbet – это не просто азарт, это философия, которая помогает вам выразить себя.
    Хотите больше возможностей для выигрыша? Обращайтесь на onexbet, и ваши мечты станут реальностью.
    onexbet – это не просто компания, это ваш путь к финансовой независимости, который вы искали.
    onexbet – это идеальное место для тех, кто ищет азарт и адреналин, но при этом ценит профессионализм и конфиденциальность.
    Доступ к самым популярным играм и событиям на onexbet, все это гарантировано для вас.
    Хотите выигрывать больше? Присоединяйтесь к onexbet, и вы обязательно останетесь довольны.
    NelsonHaywood https://arxbetdsrdg.com/user/nelsonhaywood/ .

  112. Jeuretro说:

    want to know how to get to amazon storefront? search for the brand or click the seller’s name on a product page to access their store. this guide explains how to browse storefronts for customized products, promotions, and brand content.

  113. onexbet_oxei说:

    Самый популярный букмекер onexbet, заходите и выигрывайте онлайн|Успешные ставки на спорт с onexbet, ставьте деньги и получайте прибыль|Защитите свои деньги с onexbet, играйте честно и безопасно|Приятные сюрпризы от onexbet, получите дополнительные ставки бесплатно|Играйте в казино онлайн на onexbet, наслаждайтесь игрой в любое время суток|Быстрые выплаты на onexbet, играйте без задержек и проблем|Законные ставки на onexbet, ваша безопасность – важнее всего|Онлайн трансляции спортивных событий на onexbet, выигрывайте, не выходя из дома|Получайте эксклюзивные предложения от onexbet, бонусы и подарки ждут вас|Уникальный опыт азартных игр в реальном времени, ощутите атмосферу настоящего казино|Следите за результатами на onexbet, анализируйте статистику и делайте выигрышные ставки|Заработайте на ставках с onexbet, получайте прибыль без лишних затрат|Больше шансов на успех с onexbet, делайте ставки с выгодой и уверенностью|Решаем любые вопросы и проблемы с onexbet, наши специалисты помогут вам 24/7|Уникальный дизайн и удобство на onexbet, новый уровень игрового опыта|Играйте и выигрывайте крупные суммы, не упустите возможность стать богаче|Зарабатывайте на ставках с onexbet, играть и выигрывать стало проще|Играйте и зарабатывайте больше, получайте индивидуальные предложения и бонусы|Получайте прибыль от онлайн ставок на onexbet, делайте прогнозы и получайте прибыль|Профессиональная букмекерская контора onex
    download one x bet download one x bet .

  114. DavidTah说:

    bilan o’yin-kulgi dunyosiga xush kelibsiz 1win casino! 1000 dan ortiq o’yinlar, jonli dilerlar, sport va e-sport bir joyda. Saxiy bonuslar, tezkor depozitlar va qulay pul olish. O’ynang, g’alaba qozoning va yangi his-tuyg’ularga qayting!

  115. DavidBer说:

    Discover the best game codes https://rxguides.net in-depth guides, and updated tier lists for your favorite games! Unlock exclusive rewards, master gameplay strategies, and find the top characters or items to dominate the competition.

  116. GeorgeNourn说:

    найкращі фільми онлайн дивитися фільм

  117. EddieAnemn说:

    Online casinos link are thousands of slots, live games, profitable promotions and instant wins. Try your luck in a comfortable and safe environment, enjoying the excitement at any time and from any device.

  118. Williamacarl说:

    Откройте для себя инновации с samsung md широкий выбор смартфонов, планшетов, телевизоров и бытовой техники. Выгодные цены, гарантия качества и быстрая доставка. Закажите оригинальную продукцию Samsung прямо сейчас и наслаждайтесь технологиями будущего!

发表评论

您的电子邮箱地址不会被公开。