为什么不用原生Spring-Cloud-Config

戳蓝字“CSDN云计算”关注我们哦!

引言

近几年传统应用架构已经逐渐朝着微服务架构演进。那么随着业务的发展,微服务越来越庞大,此时服务配置的管理变得会复杂起来。为了方便服务配置文件统一管理,实时更新,配置中心应运而生。
其实,所谓配置中心,就是将配置的数据放在某种存储介质中,该介质可以是

  • File(例如Git、Svn)

  • Database(例如mysql、oracle)

  • nosql Database(例如Redis、Memacache、MongoDb)

  • 其他第三方中间件(例如Zookeeper)

那么配置中心可以简单理解为是封装了对这些介质进行操作的接口,供客户端拉取使用。

由于我们采用的是Spring-Boot的架构,因此当时自然而然会考虑到Spring-Cloud中提供的配置中心Spring-Cloud-Config,但是当时做完调研以后,觉得并不能直接用。
因此,本文想来分享一下,原生Spring-Cloud-Config的配置中心的缺点,以及我们对Spring-Cloud-Config做了哪些改动。

正文

OK,我们当时做配置中心的选型的时候。第一选择是Spring-Cloud- Config。
Spring-Cloud-Config在存储介质的选择这块,基本上网上所有的文章都在推荐使用Git,即将配置文件放在Git中,服务端从Git中读取。其实官网上讲的最详细的配置,也是采取用Git作为存储介质。
因此,我相信大部分读者在生产上也是用Git作为存储介质,搭配Spring-Cloud-Config使用。
但是呢,博主认为以Git作为存储介质存在一些硬伤。

Git的权限控制是个坑

Git的权限管理是说控制用户能不能Push或者Delete分支,或者能不能Push代码,而不是能不能访问某个目录的文件。
对目录和文件的可读是Git的最基本要求,不可能做到针对目录级别的不可读。
因此如果直接使用,会出现这样一种情形

不同团队之间可以互看对方配置!

于是,可能会有如下情形发生

A团队同事A:"小B,这个地方不懂怎么配?"
A团队同事B:"去看看B团队的配置,直接贴过来。"
然后B团队就会发现自己的中间件里总是会多出一些莫名奇妙的数据!

当然,你可以禁止研发直接登陆Git改配置。然后呢,基于Git研发一套配置管理系统,在上面做权限控制,但是又有几个公司这么做呢?因为,这可能带来第二个问题。

粒度问题

将配置信息放在Git中,有一个致命问题:粒度太粗了!
你每次对一条配置发生crud的操作,其带来的影响是整个文件发生变动。如果将来我们需要对某条配置做灰度发布,基于Git来做是比较麻烦的,注意了,我没说不能做,只是比较麻烦。

那么,当时我们最理想的存储介质就是数据库,将配置信息放在数据库里有两个好处

  • 基于数据库开发一套配置管理系统,显然比基于git来开发容易的多!

  • 将配置放在数据库里,每条配置对应数据库的表中的一条记录。这么做粒度够细,针对某些重要的配置,做灰度发布,实现起来就容易很多。

因此,我们采用数据库作为存储介质。庆幸的是,这一点在Spring-Cloud-Config中是支持的。在该组件下,只需要设置

spring.profiles.active=jdbc

就能够激活jdbc模式。
但是我们很快发现了一个更大的问题,也正是因为这个问题,我们不得以需要进行改写Spring-Cloud-Config。

Spring-Cloud-Config的刷新机制是个坑!

因为一个配置中心应该要能够做到,配置发生改动的时候,项目能够自动感知,自动更新配置才对。在Spring-Cloud-Config中,这套机制是借助一些代码仓库(SVN、Github等)提供的Webhook机制加上Spring-Cloud-Bus来实现的。
在Webhook中配置一个回调地址,刷新流程如下图所示

640?wx_fmt=png


OK,那么问题又来了!
(1)配置数据放在数据库中,数据库里没有Webhook这种东西啊,怎么做到实时刷新?
(2)Spring-Cloud-Config的这套刷新机制依赖于消息总线,依赖于消息队列,存在延迟的情况!且依赖于消息队列的可用性,系统的复杂度大大增加。如果生产环境上消息队列出问题了,我们的刷新功能就会受到影响!

所以,笔者认为这套刷新机制并不是很尽如人意,需要进行修改。因此,我们很自然而然的想到了利用长轮询来改写Spring-Cloud-Config的刷新机制!

长轮询是什么

既然有长轮询,那必定有短轮询,我顺便讲讲短轮询是什么!
假设我们有一个需求

在页面上要实时显示后台的库存数量!比如库存减少了,用户不需要进行刷新,页面上的数字自己会变化。

那么,如果采取短轮询就是在客户端(js)中不断访问后台,后台接到请求马上返回最新的库存数,然后刷新到这个页面当中。
短轮询的缺点?
很明显资源浪费。假设有几百人打开了该页面,就有几百个请求在不停的请求服务端,明显听着就不合理。

因此,自然就有了长轮询的出现!
其实也很简单,客户端(js)依然是不断的去请求。但是呢,服务端不是马上返回。而是等待库存数量变化了再返回。大家知道,HTTP都有超时时间。如果在该时间内,依然没有变化,客户端将再次发起请求。

注意了,长短轮询对于客户端来说是没有区别的,就是不断的轮询。但是对于服务端,区别就比较大了。在短轮询情况下,服务端对于每次请求不管有没有变化都会立即返回结果。而长轮询情况下,如果有变化才会立即返回结果。而如果没有变化,服务端则不会再立即给客户端返回结果,直到超时为止。 

怎么实现

那么,我们在项目中采用Spring的DeferredResult来实现。在Servlet3.0以后引入了异步请求之后,Spring封装了一下提供了相应的支持,也就是DeferredResult,能够极大的提升吞吐量。
可能有人对Servlet的异步化不熟,我大概介绍一下。我们平时常用的是同步Servlet,其执行流程如下图所示

640?wx_fmt=png

缺点很明显啦 ,业务逻辑线程和servlet容器线程是同一个,一般的业务逻辑总得发生点IO,比如查询数据库,比如产生RPC调用,这个时候就会发生阻塞,而我们的servlet容器线程肯定是有限的,当servlet容器线程都被阻塞的时候我们的服务这个时候就会发生拒绝访问,从而吞吐量上不去!
那么,你使用异步Servlet如下图所示

640?wx_fmt=png

在异步Servlet中,业务线程有自己的线程池进行处理,并不会占用Tomcat中的线程,从而提升了吞吐量!

那么,怎么利用DeferredResult怎么实现长轮询呢?流程如下
(1)客户端和服务端建立TCP连接
(2)客户端发起HTTP请求
(3)服务端发起请求,监听60s内是否有配置发生变动(如何监听配置发生变动?)
(4)如果没发生变动,给客户端返回304标志位,客户端继续发起请求
(5)如果发生了变动,服务端会调用DeferredResult.setResult返回200状态码,客户端收到响应结果后,会发起请求获取变更后的配置信息。

最后一个问题:如何有效快速的监听出配置表的数据发生了变动?
因为我们用的是mysql。这里有一个Mysql的自定义函数叫mysql-udf-http。具有http_get()、http_post()、http_put()、http_delete()四个函数,可以在MySQL数据库中利用HTTP协议进行REST相关操作。
然后再和mysql的触发器结合起来用,可以实现在配置表发生变动的时候,主动通知我们的配置中心服务端。让服务端明白配置发生了变动!

一个疑问

采用长轮询技术来实现配置刷新,客户端和服务端需之间需要一直保持TCP连接进行通信。可能有些朋友会担心,到底服务端能撑多少的连接?可能觉得对性能有影响?
这里给出参考配置
使用了内存8G、4核的虚拟机约可以撑8000左右的连接!

总结

最后这套配置中心,我基于原有的Spring-Cloud-Config,改写其中的刷新机制,更加符合我们的业务场景!现已将改写思路说清,大家可以自行尝试!


推荐阅读

  • 5G大规模商用来临之前,你必须知道的几个知识点

  • “离开360时,它只给了我一块钱”

  • AI找Bug,一键快速预测

  • 原子互换:一统公链江湖的神来之笔

  • 春晚鬼畜 B 站日排行最高,赵本山:我的时代还没有结束!

  • PDF翻译神器,再也不担心读不懂英文Paper了

  • 新闻联播也可以拿来做数据分析?

  • 高晓松侃5G!2019开年大讲揭示运营商的秘密


1.微信群:

添加小编微信:color_ld,备注“进群+姓名+公司职位”即可,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!


2.征稿:

投稿邮箱:liudan@csdn.net;微信号:color_ld。请备注投稿+姓名+公司职位。

640?wx_fmt=png喜欢就点击“好看”吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/524732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cesium实现区域贴图及加载多个gif动图

1、cesium加载多个gif动图 Cesium的Billboard支持单帧纹理贴图,如果能够将gif动图进行解析,获得时间序列对应的每帧图片,然后按照时间序列动态更新Billboard的纹理,即可实现动图纹理效果。为此也找到了相对于好一点的第三方库libg…

C语言 strcpy_s 函数 - C语言零基础入门教程

目录 一.strcpy 函数简介二.strcpy 函数实战 1.strcpy 函数简单使用2.strcpy 函数拷贝内容以’\0’结尾3.strcpy 函数注意崩溃问题 三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.strcpy 函数简介 C 语言在 string.h 中strcpy函数,可用完成…

Lock锁详细讲解

package com.wuming.thread;import java.util.concurrent.locks.ReentrantLock;//测试Lock锁 public class TestLock {public static void main(String[] args) {TestLock2 testLock2 new TestLock2();//多个对象操作同一个资源票,不用lock时线程不安全/* 1089765…

DevOps“兵器”60样,你都会使哪几样?

戳蓝字“CSDN云计算”关注我们哦!编前按:获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 DevOps。一、开发工具版本控制&协作开发1.版本控制系统 GitGit是一…

synchronized和lock

区别: lock手动开启和关闭锁,synchronized出了作用域自动释放 lock只要代码块锁,synchronized有方法锁和代码块锁 lock锁jvm花费较少的时间调度线程,性能更好,更好的扩展性(提供更多的子类) …

C语言 memcpy 函数 - C语言零基础入门教程

目录 一.memcpy 函数简介二.memcpy 函数实战 1.memcpy 函数简单使用2.strcpy 函数属于字符串拷贝3.memcpy 函数属于内存拷贝4.memcpy 函数注意崩溃问题 三.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.memcpy 函数简介 C 语言在 string.h 中…

云漫圈 | 腾讯面试,我竟然输给了final关键字

戳蓝字“CSDN云计算”关注我们哦!作者:乔戈里来源:程序员乔戈里腾讯面试现场——————final 在 Java 中是一个保留的关键字,可以声明变量、方法、类。什么是final变量 / 类 / 方法?任何变量前被 final 修饰就是 fin…

C语言 memcpy_s 函数 - C语言零基础入门教程

目录 一.memcpy_s 函数简介 1.memcpy 函数报错:error C49962.memcpy 函数没有方法来保证有效的缓冲区尺寸,使用不安全 二.memcpy_s 函数语法三.memcpy_s 函数实战四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.memcp…

多线程:生产者消费者问题

1.假设仓库只能存一件产品,生产者将产品放入仓库,消费者将产品从仓库取出 2.仓库没有产品,生产者将产品放仓库,否则停止生产并等待,直到仓库产品被消费者取走 3.如果仓库放有产品,消费者可取走&#xff0…

学习微服务网关zuul,看这篇就够了

戳蓝字“CSDN云计算”关注我们哦!作者:爱撒谎的男孩 原文:https://chenjiabing666.github.io/2018/12/25/zuul%E6%9C%8D%E5%8A%A1%E7%BD%91%E5%85%B3/本文系读者投稿,已获作者原创授权。如果你有好文章,可以戳这里投稿…

C语言 strcat 函数 - C语言零基础入门教程

目录 一.strcat 函数简介二.strcat 函数原理三.strcat 函数实战四.注意 strcat 函数崩溃问题五.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.strcat 函数简介 前面文章中介绍了关于字符串拷贝的相关函数,例如:strcpy…

多线程:管cheng法

package com.wuming.thread;//测试:生产者消费者模型,利用缓冲区解决:管程法 //生产者,消费者,产品,缓冲区 public class TestPC {public static void main(String[] args) {SynContainer container new S…

C语言 strcat_s 函数 - C语言零基础入门教程

目录 一.strcat_s 函数简介二.strcat_s 函数原理三.strcat_s 函数实战四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.strcat_s 函数简介 前面文章中介绍了关于字符串拼接函数 strcat ,而 strcat_s 函数和 strcat 函数一样&…

写给程序员的裁员防身指南

戳蓝字“CSDN云计算”关注我们哦!大家都知道 18 年底许多大公司都开始了「人员优化」动作,不仅仅美团等大厂有所行动,就连一些平时求贤若渴的小公司也有所动作。本来我以为关于劳动法的事情,许多人应该多多少少都应该了解。但最近…

多线程:信号灯法

package com.wuming.thread;//测试生产者消费者问题2:信号灯法,标志位解决 public class TestPc2 {public static void main(String[] args) {TV tv new TV();new Player(tv).start();new Watcher(tv).start();} } //生产者-->演员 class Player ext…

C语言 va_start 宏 - C语言零基础入门教程

目录 一.前言二.va_start 简介三.va_start 使用四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.前言 对 printf 函数的使用,我们并不陌生,首先我们来看看下面关于 printf 函数的几种调用方式: printf(&q…

使用Kubernetes和Docker将Spring Boot与MongoDB作为容器部署

戳蓝字“CSDN云计算”关注我们哦!对于本教程,您将拥有一个Docker化Spring-Boot实例程序,该应用程序与MongoDB通信以获取GET/POST API请求,并部署在Kubernetes集群中。前提条件MinikubeKubectlDockerMavenDocker是一个具有"社…

C语言 va_end 宏 - C语言零基础入门教程

目录 一.前言二.va_end 简介三.va_end 使用四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.前言 对 printf 函数的使用,我们并不陌生,首先我们来看看下面关于 printf 函数的几种调用方式: printf("…

5种数据分析常用的思维方法!

戳蓝字“CSDN云计算”关注我们哦!转自:中国统计网来源:网络大数据在数据分析中,数据分析思维是框架式的指引,实际分析问题时还是需要很多“技巧工具”的。就好比中学里你要解一元二次方式,可以用公式法、配…

多线程总结

package com.wuming.thread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;//多线程总结 public class ThreadNew {public static void main(String[] args) {new MyThread1().start();new…