说明:来源于网络,如有侵权请联系我删除
1.提问:如果注册中心宕机,远程调用还能成功吗
答:当微服务发起请求时,会向注册中心请求所有的微服务地址,然后在向指定的微服务地址发起请求。在设计实现时,如果每次都向注册中心发起请求,然后在调用微服务地址,这样浪费性能。这时会有一个实例缓存的东西来解决这一问题。当发起请求时,先从实例缓存中查找,如果有,就直接用里面的微服务地址调用。如果没有,就向注册中心发起请求,获取微服务地址,然后在放入实例缓存中,接着调用微服务地址,下次调用时,就直接从实例缓存中拿来用。同时实例缓存和注册中心也是有一个实时更新的同步机制。了解了这样的一个设计原理,那么这个问题就比较好回答了。
分两个情况,如果这个微服务地址没有访问过,那么需要向注册中心请求获取地址,这时如果注册中心宕机,那么是无法获取地址的,也就无法访问两天。如果这个地址被访问过,那么它就会被放在实例缓存里面,此时优先从实例缓存中拿地址,而并不需要从注册中心请求,这种情况,是可以正常访问这个微服务地址的。
2.Nacos配置中心
nacos配置中心可以配置微服务的变量,同时支持不停机更新,很方便
按上图操作,即可实现nacos配置
1.启动nacos
下载nacos后,进入bin目录,然后打开cmd,运行如下命令:
D:\soft\nacos-server-2.4.3\nacos\bin>startup.cmd -m standalone
2.配置依赖
1)在services的pom文件中引入依赖
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
3.application.properties配置
在order的application.properties里面配置如下:
spring.config.import=nacos:service-order.properties
4.nacos页面配置数据集
在nacos页面配置列表里面点击创建配置
填入以下信息如下图,配置格式选择Properties
service-order.properties
order.timeout=30min
order.auto-confirm=7d
右下角点击发布
5.代码中使用配置的信息
1)在order微服务中编写代码
@Value("${order.timeout}")
private String timeOut;
@Value("${order.auto-confirm}")
private String aotuConfirm;
//获取配置
@GetMapping("/getConfig")
public String getConfig(){
return "timeout: "+timeOut + "; auto-confirm" +aotuConfirm;
}
2)重启服务,并在浏览器输入http://localhost:8000/getConfig 回车
可以看到已经成功引用了nacos配置的内容
如果想在nacos中修改了配置内容后,不用重启微服务就可生效,可以加一个注解
@RefreshScope
@RefreshScope
@RestController
public class OrderController {
@Value("${order.timeout}")
private String timeOut;
@Value("${order.auto-confirm}")
private String aotuConfirm;
@Autowired
OrderService orderService;
//创建订单
@GetMapping("/create")
public Order createOrder(@RequestParam("userId")Long userId,@RequestParam("productId")Long productId){
Order order = orderService.createOrder(productId,userId);
return order;
}
//获取配置
@GetMapping("/getConfig")
public String getConfig(){
return "timeout: "+timeOut + "; auto-confirm" +aotuConfirm;
}
}
可以修改下nacos中的数据验证,记得需要发布后才生效
3.Nacos配置中心自动刷新
当数据量很多的时候,上面的配置就不太方便了。可以使用如下方式:
1)创建配置类
输入properties.OrderProperties,生成如下类
@Component
@ConfigurationProperties(prefix="order")
@Data
public class OrderProperties {
String timeOut;
String autoConfirm;
}
其中注解@ConfigurationProperties 指定以order开头的变量。类里面的变量跟nacos里面配置的变量,需要符合驼峰命名。这样配置,可以实现自动刷新。
改造代码,应用上面的配置
//@RefreshScope
@RestController
public class OrderController {
/* @Value("${order.timeout}")
private String timeOut;
@Value("${order.auto-confirm}")
private String aotuConfirm;*/
@Autowired
OrderService orderService;
@Autowired
OrderProperties orderProperties;
//创建订单
@GetMapping("/create")
public Order createOrder(@RequestParam("userId")Long userId,@RequestParam("productId")Long productId){
Order order = orderService.createOrder(productId,userId);
return order;
}
//获取配置
@GetMapping("/getConfig")
public String getConfig(){
//return "timeout: "+timeOut + "; auto-confirm" +aotuConfirm;
return "timeout: "+orderProperties.getTimeOut() + "; auto-confirm" +orderProperties.getAutoConfirm();
}
}
重启微服务程序,页面输入http://localhost:8000/getConfig回车,看到输出以下内容
nacos配置中修改两个变量,然后发布
发布后,重新在浏览器刷新,返回值已改变
4.Nacos配置监听
使用NacosConfigManager监听配置变化
假如说service-order.properties中有变量变化,立即发邮件
实现步骤:
1.项目启动时,监听配置文件变化
2.发生变化时拿到变化值
3.发送邮件
在启动类里面写。
代码如下:
//项目启动时执行
@Bean
ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager){
return args->{
System.out.println("=========");
ConfigService configService = nacosConfigManager.getConfigService();
configService.addListener("service-order.properties", "DEFAULT_GROUP", new Listener() {
@Override
public Executor getExecutor() {
return Executors.newFixedThreadPool(4);
}
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("变化的信息为:"+configInfo);
//模拟邮件发送
System.out.println("邮件发送:"+configInfo+"变量发生变化请注意");
}
});
};
}
重启微服务,然后修改nacos中的变量
发布变量。查看服务台
可以看到成功监听到了。
5.问题:假如nacos中配置的变量和项目里面的properties文件中的变量重合了,都有值,以哪个为准?
根据上图可以知道,nacos开发的初衷就是便于统一管理变量,而且nacos属于导入的,因此假如nacos和项目本身的配置重合时,优先取nacos中的。而且如果nacos导入的properties有多个,假如配置如下:
spring.config.import=nacos:service-order.properties,nacos:common.properties
如果service-order.properties和common.properties中也有重合的变量,那谁先导入的就是优先使用的,也就是优先使用service-order.properties里面的变量。
6.nacos数据隔离
当微服务运行时,需要区分是生产环境还是测试或者开发环境。因此,需要一个方案能区分运行环境(pro、dev、test)、微服务(order、product)、properties数据集(common.properties、database.properties)。nacos很好的解决了这个问题。
将环境跟命名空间对应,微服务跟group分组对应,配置跟数据集对应,即可解决。
1)创建命名空间
输入dev dev 开发 如下图,确定
然后再创建prod生产和test测试环境。
2)在命名空间中创建properties,其中group对应的是微服务,properties对应数据集
order.timeout=1min
order.auto-confirm=1h
然后发布
然后创建database.properties ,发布
order.db-url=order_dev
此时dev环境已经建好了。
下面使用克隆创建test和prod环境的properties。
克隆好后,进入test命名空间,进行编辑,修改下变量的值,然后发布就可以了。
生产环境也调整下变量值然后发布
上面我们配置好了order的properties,下面我们配置下product的。
配置好发布后,然后再克隆给其他环境
然后修改下变量的值
测试修改为32 生产修改为40 。至此变量配置已完成。
3)在代码中加载变量
1.application.properties文件中的变量废弃
2.创建application.yml文件
输入application.yml
配置文件内容
server:
port: 8000
spring:
application:
name: service-order
cloud:
nacos:
server-addr: 127.0.0.1:8848
config:
namespace: dev
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
@Component
@ConfigurationProperties(prefix="order")
@Data
public class OrderProperties {
String timeOut;
String autoConfirm;
String dbUrl;
}
@RestController
public class OrderController {
/* @Value("${order.timeout}")
private String timeOut;
@Value("${order.auto-confirm}")
private String aotuConfirm;*/
@Autowired
OrderService orderService;
@Autowired
OrderProperties orderProperties;
//创建订单
@GetMapping("/create")
public Order createOrder(@RequestParam("userId")Long userId,@RequestParam("productId")Long productId){
Order order = orderService.createOrder(productId,userId);
return order;
}
//获取配置
@GetMapping("/getConfig")
public String getConfig(){
//return "timeout: "+timeOut + "; auto-confirm" +aotuConfirm;
return "timeout: "+orderProperties.getTimeOut() + "; auto-confirm" +orderProperties.getAutoConfirm()
+"; dburl=" +orderProperties.getDbUrl();
}
}
重启项目,页面输入http://localhost:8000/getConfig
返回成功数值。
修改yml文件中的启动变量为test
重启服务,页面刷新后得到如下结果,变量生效
同理修改为prod也会得到对应结果
但是如上yml配置有问题,如果每个环境加载的properties不一样,这种方式就不行了。做如下修改:
server:
port: 8000
spring:
profiles:
active: prod
application:
name: service-order
cloud:
nacos:
server-addr: 127.0.0.1:8848
config:
import-check:
enabled: false
namespace: ${spring.profiles.active:dev}
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
activate:
on-profile: dev
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
- nacos:haha.properties?group=order
activate:
on-profile: test
---
spring:
config:
import:
- nacos:common.properties?group=order
- nacos:database.properties?group=order
- nacos:haahaa.properties?group=order
activate:
on-profile: prod
这样每次修改下active的值即可区分不同的环境变量