Spring cloud Eureka服务注册中心
- 一、注册中心
- 二、存在意义
- 三、角色
- 四、运行流程
- 五、入门案例
- 1、创建Spring Cloud 工程
- 2、创建 Eureka 服务
- pom.xml
 
 
- 3、配置 application.yml
- 4、服务间调用
- 方式一:RestTemplate + DiscoveryClient
- 方式二:RestTemplate + LoadBalancerClient
- 方式三:RestTemplate + @LoadBalanced
 
 
- 六、Eureka 原理
- 七、CAP原则
- 取舍策略:
 
 
- 八、自我保护
- 1、Eureka收不到服务的情况:
- 2、自我保护模式
- 3、关闭自我保护
 
 
- 九、优雅停服
- 1、依赖
- 2、配置
- 4、停服
 
 
- 十、认证授权
- 1、依赖
- 2、配置
- 2.1 Eureka配置
- 2.2 服务配置
- 2.3 过滤CSRF(跨域请求伪造)
- 方式一:使 CSRF 忽略 /eureka 的所有请求
- 方式二: 保持密码验证的同时禁用CRSF防御机制
 
 
 
 
 
一、注册中心
 注册中心就是微服务架构中的通讯录,它记录了服务和服务地址的映射关系,在分布式架构中,服务会注册到这里,服务通过注册中心调用其他服务。
二、存在意义
 注册中心主要进行服务管理和服务依赖关系管理
- 服务注册后及时发现
- 负载均衡
- 服务宕机后即使下线
- 水平拓展服务
- 服务发现后处理路由
- 服务异常后的降级处理
三、角色
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z06hxC1n-1670555809009)(img/Eureka注册中心角色.jpeg)]](https://img-blog.csdnimg.cn/2ca57020f37d4f34abb83d9938c9f99d.png)
- Eureka Server :通过 Register、Get、Renew 等接口提供服务的注册和发现
- Server Provider(Application Service): 服务提供方,把自身的服务实例注册到 Eureka Server 中
- Server Consumer(Application Service):服务调用方,通过 Eureka Server 获取服务列表,消费服务
四、运行流程
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zDKFEadd-1670555809010)(img/Eureka注册中心运转流程.jpeg)]](https://img-blog.csdnimg.cn/a8ddf5865f7648d59cec79d20f778404.png)
0:实例化服务
1:将服务注册到注册中心
2:注册中心收录服务
3:从服务中心获取服务列表
4:基于负载均衡从地址列表中选择服务地址进行服务调用
5:定期发送心跳
6:检查没有定期发送心跳的服务,并在一定时间内剔除服务地址列表
五、入门案例
1、创建Spring Cloud 工程
2、创建 Eureka 服务
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>com.byx</groupId>
      <artifactId>scaffold-parent</artifactId>
      <version>0.0.1</version>
      <relativePath>../parent</relativePath>
   </parent>
   <artifactId>scaffold-eureka</artifactId>
   <packaging>${packaging.type}</packaging>
    
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
         <exclusions>
            <exclusion>
               <groupId>org.junit.vintage</groupId>
               <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
         </exclusions>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>
application
package com.byx.scaffold.rcentre;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class ServiceRegistrationAndDiscoveryApplication {
   public static void main(String[] args) {
      SpringApplication.run(ServiceRegistrationAndDiscoveryApplication.class, args);
   }
}
3、配置 application.yml
spring:
  application:
    name: eureka                 # 应用名称
server:
  port: 8761                     # 端口
eureka:
  instance:
    hostname: localhost          # 主机名
    prefer-ip-address: true
  client:
    register-with-eureka: false  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: false        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址
      defaultZone: http://toolKit:dily1314@localhost:8761/eureka/
4、服务间调用
方式一:RestTemplate + DiscoveryClient
启动类或配置中增加 RestTemplate Bean
//@EnableEurekaClient 如果配置了注册中心,则会默认开启,无需使用该注解
@SpringBootApplication
public class ConsumerApplication {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    };
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
Service 中调用服务
@Service
public class OrderService {
    @Autowired
    private RestTemplate restTemplate;   // 启动类 或者 Config 中 要注入bean
    @Autowired
    private DiscoveryClient discoveryClient;
    public Order getList() {
        return new Order(1, "202020202020", selectProductListWithBalancer("provider", "/product/list"));
    }
    /**
     * 跨服务调用
     * 无负载均衡
     *
     * @param service 服务名
     * @param api     接口
     * @return 结果
     */
    private List<?> selectProductList(String service, String api) {
        StringBuffer sb = new StringBuffer();
        // 获取服务方法
        List<String> services = discoveryClient.getServices();
        if (CollectionUtils.isEmpty(services))
            return null;
        // 根据服务名获取服务
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances(service);
        if (CollectionUtils.isEmpty(serviceInstances))
            return null;
        ServiceInstance si = serviceInstances.get(0);
        sb.append("http://" + si.getHost() + ":" + si.getPort() + api);
        // 返回数据
        ResponseEntity<List<?>> response = restTemplate.exchange(
                sb.toString(),
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<?>>() {
                }
        );
        return response.getBody();
    }
}
方式二:RestTemplate + LoadBalancerClient
启动类或配置中增加 RestTemplate Bean
//@EnableEurekaClient 如果配置了注册中心,则会默认开启,无需使用该注解
@SpringBootApplication
public class ConsumerApplication {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    };
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
Service 中调用服务
@Service
public class OrderService {
    @Autowired
    private RestTemplate restTemplate;   // 启动类 或者 Config 中 要注入bean
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    public Order getList() {
        return new Order(1, "202020202020", selectProductListWithBalancer("provider", "/product/list"));
    }
    /**
     * 跨服务调用
     * 有负载均衡
     *
     * @param service 服务名
     * @param api     接口
     * @return 结果
     */
    private List<?> selectProductListWithBalancer(String service, String api) {
        StringBuffer sb = new StringBuffer();
        // 根据服务名 通过负载均衡 获取服务
        ServiceInstance si = loadBalancerClient.choose(service);
        if (si == null)
            return null;
        sb.append("http://" + si.getHost() + ":" + si.getPort() + api);
        // 返回数据
        ResponseEntity<List<?>> response = restTemplate.exchange(
                sb.toString(),
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<?>>() {
                }
        );
        return response.getBody();
    }
}
方式三:RestTemplate + @LoadBalanced
启动类或配置中增加 RestTemplate Bean 加入注解 @LoadBalanced
//@EnableEurekaClient 如果配置了注册中心,则会默认开启,无需使用该注解
@SpringBootApplication
public class ConsumerApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    };
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}	
六、Eureka 原理
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWYIZRcB-1670555809010)(img\Eureka原理图.jpeg)]](https://img-blog.csdnimg.cn/8ff1bd55587f406e90e57d23e66f59be.png)
七、CAP原则
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pj6Jhtj7-1670555809011)(img\CAP原则.jpeg)]](https://img-blog.csdnimg.cn/fc1b2d3f9d3244798965d9e9f61b12ce.png)
C: 一致性
A: 高可用
P: 分区容错
 金融: CP(大型) 、AP(互联网)
取舍策略:
-  CA: 如果不要求 P(不允许分区),则 C(强一致性)和 A(高可用性)是可以保证的.放弃P意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计初衷的。 
-  CP:如果不要求 A(不要求高可用),则 C 相当于每个请求都需要在服务之间保持强一致性,而 P (分区容错)会导致同步时间无线延长(也就是等待数据同步才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致后再让用户访问系统。设计成 CP 的系统其实不少,最典型的就是分布式数据库,如:redis,对于分布式数据库来说,数据的一致性时最基本的要求。 
-  AP:要求高可用并允许分区容错,则放弃一致性,一旦分区发生,节点之间可能失去联系,为了高可用,每个节点都只能使用本地数据提供服务,而这会导致全局数据不一致,典型应用就是抢购商品的场景,可能浏览的页面还显示有商品,但是下单的时候发现商品已经售完,这其实就是在A(高可用)方面保证可以正常服务,在数据一直性方面做了牺牲。 
八、自我保护
一般情况,服务在 Eureka 注册后 每30s 发送一次心跳,Eureka 通过心跳包来判断服务是否健康,同时会定期删除超过 90s 没有发送心跳的服务。
在服务不可以时,不会立即释放服务信息,而是保存一段时间后再删除。
1、Eureka收不到服务的情况:
- 微服务自身原因
- 微服务与 Eureka 之间的网络故障
2、自我保护模式
在运行期间,Eureka 会统计心跳失败比例,如果 15 分钟内的低于 85%,Eureka 会将这些实例保护起来,让这些实例不会过期,同时提醒一个警告
3、关闭自我保护
eureka:
  server:
    enable-self-preservation: false # true 开启自我保护, false 关闭自我保护
    eviction-interval-timer-in-ms: 60000 # 清除隔离(单位:毫秒) 默认 60 * 1000
九、优雅停服
配置优雅停服后,无需配置关闭自我保护,这里用actuator实现
1、依赖
<!--        优雅停服-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、配置
# 度量指标监控与健康检查
management:
  endpoints:
    web:
      exposure:
        include: shutdown   # 开启 shutdown 端点访问
  endpoint:
    shutdown:
      enabled: true # 开启 shutdown 实现优雅停服
4、停服
向需要停服的服务地址发送 shutdown 请求
服务地址:172.10.16:8080
停服请求:Post方式 172.10.16:8080/actuator/shutdown
十、认证授权
1、依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、配置
2.1 Eureka配置
spring:
  # 安全认证
  security:
    user:
      name: root       # 用户名
      password: 123456 # 密码
2.2 服务配置
eureka:
  instance:
    hostname: localhost
  client:
    service-url:
    # 前面加用户名:密码
      defaultZone: http://root:123456@localhost:8761/eureka/
2.3 过滤CSRF(跨域请求伪造)
方式一:使 CSRF 忽略 /eureka 的所有请求
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        supper.configure(http)  // 访问eureka 的控制台和/actuator 是可以做安全控制
        http.csrf().ignoringAntMatchers("/eureka/**"); //忽略eureka/**的所有请求
    }
}
方式二: 保持密码验证的同时禁用CRSF防御机制
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http // 直接disable 会把安全验证也禁用,
            .csrf().disable().authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic();
    }
}









![[附源码]JAVA毕业设计翔隆生鲜超市进货管理系统(系统+LW)](https://img-blog.csdnimg.cn/2a112239172e4c31b023ff003f8d29fd.png)








