Eureka
1、创建服务端
server:
port: 8761 # eureka 默认端口
spring:
application:
name: eureka-server # 应用名称(微服务中建议必须定义应用名称)
@SpringBootApplication
@EnableEurekaServer // 开启eureka注册中心功能
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2、创建客户端
# 应用服务 WEB 访问端口
server:
port: 8080
spring:
application:
name: eureka-client-a
eureka:
client:
service-url: # 指定注册地址
defaultZone: http://localhost:8761/eureka
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientBApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientBApplication.class, args);
}
}
# 应用服务 WEB 访问端口
server:
port: 8081
spring:
application:
name: eureka-client-b
eureka:
client:
service-url: # 指定注册地址
defaultZone: http://localhost:8761/eureka
服务端(注册中心)配置
服务端(注册中心)配置需要考虑的问题:
- 在注册中心维护一个容器列表,保存服务应用的信息
- 应用下线以后,及时从容器中移除
- 应用之间访问应该向注册中心缓存一份服务列表,但是如何避免脏读问题
server:
port: 8761 # eureka 默认端口
spring:
application:
name: eureka-server # 应用名称(微服务中建议必须定义应用名称)
# eureka 配置分为三类:server client 实例
eureka:
server:
eviction-interval-timer-in-ms: 10000 # 服务端每隔10s做定期删除工作(删除过期服务)
renewal-percent-threshold: 0.85 # 续约百分比阈值(超过85%的服务没有续约,那么eureka会保护服务 不糊剔除任何一个)
instance: # 实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 主机名称:应用名称:端口号
hostname: localhost # 主机名称或者服务的ip
prefer-ip-address: true # 以 ip 的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 5 # 实例的续约时间间隔
客户端配置
# 应用服务 WEB 访问端口
server:
port: 8080
spring:
application:
name: eureka-client-a
eureka:
client:
service-url: # 指定注册地址
defaultZone: http://localhost:8761/eureka
register-with-eureka: true # 可以不向 eureka 注册服务
fetch-registry: true # 是否缓存一份服务列表到本地
registry-fetch-interval-seconds: 10 # 拉取的时间间隔(缓解服务列表脏读的问题)
instance:
hostname: localhost # 主机或ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true # 显示ip
lease-renewal-interval-in-seconds: 10 # 续约的时间
构建 eureka-server 集群
eureka 是一种非主从模式的去中心化的集群模式,多个节点之间互相注册同步自己的服务列表;下面我们除了上面创建好的 eureka-server(8761),再创建两台服务端(注册)节点:
- 需要在这3个服务端都配置注册地址(添加除自己之外的注册地址,相当于把自己当做一个 client)
创建 eureka-server-b:
server:
port: 8762 # eureka 默认端口
spring:
application:
name: eureka-server # 应用名称(微服务中建议必须定义应用名称)
# eureka 配置分为三类:server client 实例
eureka:
instance: # 实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 主机名称:应用名称:端口号
hostname: localhost # 主机名称或者服务的ip
prefer-ip-address: true # 以 ip 的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 5 # 实例的续约时间间隔
client:
service-url: # 指定注册地址
defaultZone: http://localhost:8761/eureka,http://localhost:8763/eureka
创建 eureka-server-c:
server:
port: 8763 # eureka 默认端口
spring:
application:
name: eureka-server # 应用名称(微服务中建议必须定义应用名称)
# eureka 配置分为三类:server client 实例
eureka:
instance: # 实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 主机名称:应用名称:端口号
hostname: localhost # 主机名称或者服务的ip
prefer-ip-address: true # 以 ip 的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 5 # 实例的续约时间间隔
client:
service-url: # 指定注册地址
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
给 eureka-server-b 和 eureka-server--c 添加注解: @EnableEurekaServer
Nacos 和 Eureka 区别:
- nacos 有命名空间和组的概念来隔离不同项目中相同的服务名称,但是 eureka 并不能隔离开(可以通过服务名称拼接项目名称的方式来隔离)
修改 application.yml:
server:
port: 8080
spring:
application:
name: nacos-client-a
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 向这个地址注册自己
username: nacos
password: nacos
添加 @EnableDiscoveryClient 注解:
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现客户端
public class NacosClientAApplication {
public static void main(String[] args) {
SpringApplication.run(NacosClientAApplication.class, args);
}
}
注意 SpringBoot 和 SpringCloud Alibaba 版本对应 :版本说明 · alibaba/spring-cloud-alibaba Wiki · GitHub
配置中心
1、nacos 创建配置:
2、编写 SpringBoot配置文件 bootstrap.yml:
server:
port: 8081
spring:
application:
name: nacos-config-a
cloud:
nacos:
config:
server-addr: localhost:8848
username: nacos
password: nacos
prefix: nacos-config-a # dataId 默认选择 spring.application.name
file-extension: yml # 配置文件的格式
# namespace: # 默认 public
# group: # 默认 DEFAULT_GROUP
这里的 prefix 就相当于是 data id (应用名称),将来就是配置文件的名称
3、编写测试类
注意:这里写得并不标准,实际开发中的写法看下面的动态配置刷新章节
@RestController
public class TestController {
@Value("${hero.name}")
private String name;
@Value("${hero.age}")
private Integer age;
@Value("${hero.address}")
private String address;
@GetMapping("/info")
public String getInfo(){
return name+":"+age+":"+address;
}
}
4、测试
动态配置刷新
实现配置动态刷新很简单,添加注解 @RefreshScope 即可,具体添加的位置:
如果是上面的代码,可以直接添加在 controller 类上,因为下面就是我们的配置属性:
@RestController
@RefreshScope
public class TestController {
@Value("${hero.name}")
private String name;
@Value("${hero.age}")
private Integer age;
@Value("${hero.address}")
private String address;
@GetMapping("/info")
public String getInfo(){
return name+":"+age+":"+address;
}
}
但是我们一般会添加在配置类Bean上面:
1、编写配置类
上面我们直接在 controller 中使用 @Value 来读取配置,实际开发中我们一般会单独创建一个配置类。创建 config 包,并创建 Hero 这个配置类:
1.1、写法1(推荐)
这里我们使用 @ConfigurationProperties + @Component 实现配置类的注入
package com.lyh.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@RefreshScope
@ConfigurationProperties(prefix = "hero")
public class Hero {
private String name;
private Integer age;
private String address;
}
使用 @ConfigurationProperties 注解需要添加该依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
1.2、写法2
使用 @Value + @Component 实现自动注入
package com.lyh.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@RefreshScope
public class Hero {
@Value("${hero.name}")
private String name;
@Value("${hero.age}")
private Integer age;
@Value("${hero.address}")
private String address;
}
2、编写 controller
@RestController
public class TestController {
@Autowired
private Hero hero;
@GetMapping("/info")
public String getInfo(){
return hero.getName()+":"+hero.getAge()+":"+hero.getAddress();
}
}
3、测试即可
配置回滚
配置文件的读取方式
nacos 配置中心通过 namespace,dataId 和 group 来唯一确定一条配置。
- namespace:默认 public
- dataId:配置文件名称
- group:组别,默认是 DEFAULT_GROUP
其中,dataId 是最重要的配置,格式为:
${prefix}-${spring.profiles.active}.${file-extension}
注意:在web控制台在写 dataId 时一定要添加文件类型后缀,比如:nacos-config-dev.yml
一个项目中读取多个配置文件(extension-configs)
注意:目前一个项目中要读取多个配置文件只支持在一个命名空间下!
如何读取相同 命名空间下不同组的配置文件:
编辑配置:
共享配置文件(shared-configs)
比如多个项目都需要操作同一个数据源(比如 mybatis,redis),那么我们可以通过共享配置文件把数据源统一进行管理。
现在我们在 nacos 创建一个共享文件:application.yml 。
写法1(不能修改 group,只能在默认组):
server:
port: 8082
spring:
application:
name: nacos-config-test
cloud:
nacos:
config:
namespace: 19519eb4-c512-4907-9127-9bda8a575125
group: A_GROUP
username: nacos
password: nacos
server-addr: localhost:8848
file-extension: yml
prefix: user-center
shared-configs:
- application-dev.yml # 这种写法只能在 DEFAULT_GROUP
profiles:
active: dev
写法2(可以修改组)
server:
port: 8082
spring:
application:
name: nacos-config-test
cloud:
nacos:
config:
namespace: 19519eb4-c512-4907-9127-9bda8a575125
group: A_GROUP
username: nacos
password: nacos
server-addr: localhost:8848
file-extension: yml
prefix: user-center
shared-configs:
- dataId: application-dev.yml
group: A_GROUP
refresh: true