技术标签: SpringCloud
配置文件命名方式参考官网,这里取其中一种:{application}-{profile}.yml
新建一个springboot项目,添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
bootstrap.yml文件配置如下:
server:
port: 8087
spring:
application:
name: config-server-svn
profiles:
active: subversion #使用svn作为配置仓库,必须显示声明profiles.active=subversion,不然还是用的git
cloud:
config:
server:
svn:
uri: http://xxx.xx.xxx.xxx/springconfig/trunk/SpringCloudConfig #配置svn仓库地址
searchPaths: respo #配置仓库路径
username: xxxxxx #访问svn仓库的用户名
password: xxxxxx #访问svn仓库的用户密码
basedir: /data #默认在系统临时目录下面,需要调整一下避免临时文件被系统自动清理
label: trunk #配置svn的分支
rabbitmq:
host: xxx.xx.xxx.xxx
port: 5672
username: xxxxxxx
password: xxxxxxxx
configServer的工作流程:
1 服务端注册客户端获取配置接口
2 健康检查时刷新svn仓库到本地
3 客户端启动和每次健康检查时调用该接口获取配置.
另起一个客户端,依赖config,actuator以及bus-amqp
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
bootstrap.yml文件配置如下:
server:
port: 8120
spring:
application:
name: microservice
cloud:
config:
uri: http://config.xxxxxxxxx.com/ #指明配置服务中心的网址
profile: test #dev开发环境配置文件,test测试环境配置文件,prod生产环境配置文件
label: trunk
fail-fast: true #拉取配置失败时快速退出,否则有时项目依旧会启动,造成某些依赖的组件为空
rabbitmq:
host: xxx.xxx.xx.xx
port: 5672
username: xxxx
password: xxxxxxx
至此仅实现客户端初始化时从配置中心拉取配置。修改配置需重启应用.如何实现客户端配置的热更新?主要是@RefreshScope这个注解,热更新redis示例:
/**
* 因为@RefreshScope注解的组件是懒加载的,所以如果有starter的话,可
* 能上下文中已经有了一个redisConnectionFactory,所以建议不要依赖自动* 装配的包,自己定义一个redis配置的组件
*/
@Configuration
@RefreshScope
public class RedisConnectionFactoryConf {
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout:2000}")
private long timeout;
@Value("${spring.redis.lettuce.pool.max-idle:5}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.min-idle:0}")
private int minIdle;
@Value("${spring.redis.lettuce.pool.max-active:10}")
private int maxActive;
@Value("${spring.redis.lettuce.pool.max-wait:2000}")
private long maxWait;
private LettuceConnectionFactory lettuceConnFactory() {
// 单机版配置
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
// 集群版配置
// RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
// String[] serverArray = clusterNodes.split(",");
// Set<RedisNode> nodes = new HashSet<RedisNode>();
// for (String ipPort : serverArray) {
// String[] ipAndPort = ipPort.split(":");
// nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
// }
// redisClusterConfiguration.setPassword(RedisPassword.of(password));
// redisClusterConfiguration.setClusterNodes(nodes);
// redisClusterConfiguration.setMaxRedirects(maxRedirects);
//连接池配置
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxTotal(maxActive);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
.poolConfig(genericObjectPoolConfig)
.build();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
lettuceConnectionFactory.afterPropertiesSet();
return lettuceConnectionFactory;
}
@RefreshScope
@Bean("lettuceRedisTemplate")
public RedisTemplate<String, String> myTemplate() {
LettuceConnectionFactory factory = this.lettuceConnFactory();
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
}
配置文件为bootstrap.yml,配置基本数据,主要包括config客户端配置。svn配置hooks到config的/actuator/bus-refresh这个接口。当有svn push事件发生时,会调用该接口,从而通过spring bus通知到客户端,客户端删除@RefreshScope的Bean缓存,以重新创建基于新配置的bean。
流程如下:
1.svn仓库push事件
2.hooks->POST configServer/actuator/bus-refresh
3.configServer publish>>Bus
4.Client subscribe>>Bus
5.refresh
这里需要注意,如果是svn配置的hooks,因其body的payload的原因,config服务端可能会解析失败,此时有如下解决方案,配置一个filter,使此request的body为空:
@WebFilter(urlPatterns = "/actuator/bus-refresh")
public class RefreshFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String url = httpServletRequest.getRequestURI();
if (!url.endsWith("/actuator/bus-refresh")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
EmptyRequestWrapper requestWrapper = new EmptyRequestWrapper(httpServletRequest);
filterChain.doFilter(requestWrapper, servletResponse);
}
return;
}
@Override
public void destroy() {
}
/**
* 返回自定义的空request
*/
private class EmptyRequestWrapper extends HttpServletRequestWrapper {
public EmptyRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
byte[] bytes = new byte[0];
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.read() == -1 ? true : false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
}
}
参考文章:
1、https://blog.csdn.net/wtdm_160604/article/details/83720391
2、https://blog.csdn.net/Sadlay/article/details/84964839
3、https://blog.csdn.net/Michael_HM/article/details/78497583
4、https://blog.csdn.net/w405722907/article/details/86712781
public class Test { public static void main(String[] args) { Student stu = null; System.out.println(stu.getName()); }}看到上述代码,运行结果是什么?NullPointerException?看下Student类吧。public class Student {
aspectJ最简单的HelloWorld例子这是aspectJ的入门。aspectJ和aop有什么区别? aspectJ也能够实现和aop功能,aop一般指spring的aop,就是指使用@Aspect/@Pointcut/@Before/@Around等注解的那一套,实现原理是动态代理。而aspectJ是更加高效的在编译器的层面上植入通知的可以猜测,aspectJ 和 lombok 类似,...
com.netflix.hystrix.HystrixCircuitBreaker是接口,HystrixCircuitBreaker是Hystrix的核心组件,HystrixCircuitBreaker作为断路器使用,有着自己的核心方法:public interface HystrixCircuitBreaker { boolean allowRequest(); boolea...
Hi~ o(* ̄▽ ̄*)ブ 小伙伴们,你想玩建模吗?次世代建模,一般是建模、雕刻、展UV、拓扑、贴图、做材质等几个步骤。在不同的步骤当中,所用到的软件有所不同。这里为大家科普下建模软件:高模:Maya、3Dmax、Zbrush中模:Maya、3Dmax低模:Maya、3Dmax、Topogun展UV:Maya、Zbrush、Unfold3D、Uvlayout烘焙:Maya、Zbrush、3Dmax、Xnormal、3DO、GrazyBump材质:Photoshop、Subst
这几天对于verlog里面reg变量赋值,导致数据delay的情况十分混论,这里理一理; 首先单独一个reg型变量在always块中,进行常数赋值或者自赋值,显然不会产生delayalways@( posedge clk or negedge rst_n )begin if( !rst_n )begin count_reg <= 0; end else
戳蓝字“CSDN云计算”关注我们哦!数据分析:喜欢果脯的朱小五内容撰写:只爱辣条的王小九本文转自公众号『凹凸数读』1块钱能买到什么?对于80、90后的童年来讲,1块钱是4...
断断续续的搞了两次,终于把这个功能实现了。1.二维码的插件2.转base64格式的工具(图像转换工具,可用于图像和base64的转换)3.uniapp安装// 以下路径需根据项目实际情况填写import { pathToBase64, base64ToPath } from '../../js/image-tools/index.js'4.pathToBase64从图像路径转...
错误信息:RMAN-05501: aborting duplication of target databaseRMAN-05001: auxiliary file name /oracle/oradata/skatedb/tbs_statspack01.dbf conflicts with a file used by the target database在用rman duplicate创建dg的时候,抛出如上的错误,这里只列出用rman dumplicate的过程,具体操作步骤如下:.
电力系统导纳矩阵计算,MATLAB这学期在上大四专业选修课时,一个课后作业是写一个电力系统的导纳矩阵计算程序,我找了找资料肝了半天的程序如下图所示,希望能对大家有用。程序说明1.具有非标准变比的变压器处理如果变压器阻抗归算到非标准变比的K侧,则在参数输入脚本文件data中变压器参数第五列记为0;如果归算到非标准变比的1侧,则在参数输入脚本文件data中变压器参数第五列记为1。2.线路为双回线时,需要将两个节点之间线路阻抗减半,导纳加倍;同时,如果线路是双回线则在data线路参数中第五列记为1,否
使用ShaderGraph制作动漫人物眼睛部分实现效果如下图:实现步骤:新建HDRP工程,创建Eye Graph(2019版还是处于预览版,正式项目慎用)节点图如下连接点这里就不详述了,官网上有详细的解释。2.人物模型使用资源为官方资源,百度链接如下:链接:https://pan.baidu.com/s/1K6SxpO7_PROLdAWKbPm5dw提取码:jkml3.新建Sample Texture 2D节点,然后创建两个Texture2D变量,分别显示眼睛和眼白图片:如上图所示,
本文实例讲述了JS+CSS实现大气清新的滑动菜单效果代码。分享给大家供大家参考,具体如下:这是一款比较大气清新的滑动导航菜单,CSS和JavaScript配合完成,鼠标放到一级菜单上,会滑出二级的菜单,兼容性也不错,适合大多数网站使用,用到两张背景图片,请拷贝图片地址下载图片。运行效果截图如下:在线演示地址如下:具体代码如下:/p>"http://www.w3.org/TR/xhtml1/D...
在我们访问wfs服务时候,有时候会遇到前台访问时候的跨域问题。这里给出java访问的一个小例子。 1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 imp...