SpringCloud系列(二):注册中心Eureka之服务端、客户端、安全认证

star2017 1年前 ⋅ 368 阅读

在学习 Eureka 之前,先了解下 Spring Cloud Netflix
  
Spring Cloud Netflix 通过自动配置和绑定 Spring 环境以及 Spring 编程模型习惯为 Spring Boot 应用程序提供 Netflix OSS 集成。通过一些简单的注释,即可快速启用和配置常见的组件,并使用经过实战考验的 Netflix 组件构建大型分布式系统,提供的组件包含服务发布(Eureka)、断路器(Hystrix)、智能路由(Zuul)、客户端负载均衡

Spring Cloud Eureka 是 Spring Cloud Netflix 套件之一;是 Netflix 服务发现服务器和客户端,主要负责服务发现;是一个基于 REST 的服务,能够方便地将服务注册到 Eureka 中进行统一管理,配置和部署高可用服务器,每个服务器将注册服务的状态复制到其他服务器(管理所有服务的信息和状态)。

Spring Cloud Netflix 项目地址Spring Cloud Netflix 文档

Eureka 注册中心(服务发现)包含服务器(Server)客户端(Client)两部份。

Eureka Server

Service Discovery: Eureka Server,注册中心服务给服务提供者注册, 服务端提供了一个主页,其中包含了位于/eureka/* 下常规的 eureka 功能的 UI 和 HTTP API 端点。

添加依赖

  1. Spring Boot 项目,添加 eureka-server 依赖包,如下

     <properties>
         <java.version>1.8</java.version>
         <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
     </properties>
    
     <dependencies>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
       </dependency>
     <dependencies>
    
     <dependencyManagement>
         <dependencies>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-dependencies</artifactId>
                 <version>${spring-cloud.version}</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
         </dependencies>
     </dependencyManagement>
    
     <repositories>
         <repository>
             <id>spring-milestones</id>
             <name>Spring Milestones</name>
             <url>https://repo.spring.io/milestone</url>
         </repository>
     </repositories>
    

    查看 Eureka Server 的依赖包,可知页面展示的端点监控信息实际是依赖于 spring-boot-starter-actuator 实现,UI页面采用的是 freemarker 模板。
    所以如果项目中已经使用了 Thymeleaf 模板,Eureka Server 的 freemarker 模板就会无法正确加载,这样就有必要手动配置模板的加载:

    spring:
     freemarker:
         template-loader-path: classpath:/templates/
         prefer-file-system-access: false
    

配置运行

  1. 在启动类上添加开启 Eureka Server 的注解 @EnableEurekaServer

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    }
    
  2. application.properties 配置文件添加如下配置。

    #定义应用名(服务名)
    spring.application.name=eureka-server
    server.port=8761
    eureka.instance.hostname=localhost
    #因自己就是注册中心,所以关闭向注册中心注册自己
    eureka.client.register-with-eureka=false
    #因注册中心的职责是维护实例,并不需要去检索服务,所以关闭
    eureka.client.fetch-registry=false
    

    eureka.client.register-with-eureka 一定要配置为 false,否则应用在启动时会把自己当作客户端向自己注册,会报错。

  3. 直接运行 EurekaServerApplication 即可启动注册中心服务(Eureka Server)了。

  4. 在浏览器直接输入 http://localhost:8761/ 即可访问 Eureka 提供的 Web 控制台。

Eureka Clients

Eureka Client 客户端应用是服务提供者,需要注册到注册中心,供服务发现。创建一个 Eureka Client 作为服务提供者,编写接口并提供服务。

添加依赖

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>

<dependencies>    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
    </repository>
</repositories>

配置运行

  1. application.properties 配置文件添加如下配置

    #端口
    server.port=8081
    #定义应用名(服务名)
    spring.application.name=sakila-service
    #eureka 注册中心地址
    eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
    
  2. 创建 Controller,编写接口

    @RestController
    @RequestMapping("/sakila")
    public class HomeController {
    
        @GetMapping("/home")
        public String home(){
            return "Hello World";
        }
    }
    
  3. 运行应用

    访问接口:http://localhost:8081/sakila/home 返回:Hello World,表示的接口成功。

  4. 刷新 Eureka Server 的 Web 控制台,在当前注册实例列表可以看到该客户端应用,表示注册成功。

  5. 配置说明

    defaultZone:是个后备配置,为任何没有指定首选项的客户端提供服务 URL,可简单理解为配置默认 URL。

消费服务接口

同样创建一个 Eureka Client 客户端应用,注册到 Eureka Server 注册中心,作为服务的消费者,来调用注册到 Eureka Server 的实例的服务接口。

  1. application.properties 配置

    #端口
    server.port=8082
    #定义应用名(服务名)
    spring.application.name=sakila-consumer
    #eureka 注册中心地址
    eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka
    
  2. 配置注册 RestTemplate Bean

    /**
     * RestTemplate配置类
     */
    @Configuration
    public class RestTemplateConfig {
    
        @Bean(name = "restTemplateOne")
        public RestTemplate restTemplateOne() {
            //设置超时时间,毫秒
            return new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(1000)).setReadTimeout(Duration.ofMillis(1000)).build();
        }
    
        @Bean(name = "restTemplateTwo")
        @LoadBalanced
        public RestTemplate restTemplateTwo(){
            //设置超时时间,毫秒
            return new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(1000)).setReadTimeout(Duration.ofMillis(1000)).build();
        }
    }
    
  3. 编写 Controller 调用服务接口

    @RestController
    @RequestMapping("/consumer")
    public class ConsumerController {
    
        @Autowired
        private RestTemplate restTemplateOne;
        @Autowired
        private RestTemplate restTemplateTwo;
    
        @GetMapping("/callHello")
        public String callHello() {
    
            //直接调用服务接口
            String url1 = "http://localhost:8081/sakila/home";
    
            //通过Eureka来调用服务接口
            String url2 = "http://sakila-service/sakila/home";
    
            String str1 = restTemplateOne.getForObject(url1, String.class);
            String str2 = restTemplateTwo.getForObject(url2, String.class);
            return str1 + "---" + str2;
        }
    }
    
  4. 浏览器访问服务消费者应用的接口,可以看到调用了服务提供者的接口,并返回正确信息。

注意:通过 Eureka 来调用其它服务,是根据 spring.application.name 属性定义的应用名(也称为服务名 或 服务ID(serviceId))来获取服务的,而不是 eureka.instance.appname 定义的实例名。

Eureka 更多描述

当项目中引入了 spring-cloud-starter-netflix-eureka-client 依赖包,应用会从配置文件中找到注册中心的 URL 地址作为 Eureka Client 自动注册到 Eureka Server。

当 Eureka Client 向 Eureka Server 注册时,Client 会提供有关自身的元数据信息,如主机地址、端口、健康指示器URL、主页和其他详信息。

Eureka Server 接收每个客户端实例发送的心跳信息以保持最新状态,如果心跳超时,通常会从注册表中删除该实例。

默认应用名称(服务名)、虚拟主机端口分别取值环境变量 ${spring.application.name}${spring.application.name}${server.port}

Eureka Client 客户端实例的行为由 eureka.instance.* 配置键驱动,如果应用程序配置了 spring.application.name(这是 Eureka 服务ID 或 优先默认值),则默认值更好。

Eureka Client 客户端会缓存一个 Eureka Server 实例注册表,也就是说,客户端不必为服务的每个请求转到注册中心(注册表包含了实例名和实例URL地址的映射,客户端可以从本地缓存的注册表直接找到目的服务器)。

更多详细配置,可参考EurekaInstanceConfigBeanEurekaClientConfigBean

若要禁用 Eureka Discovery Client, 将 eureka.client.enabled 设置为 false, 或设置 spring.cloud.discovery.enabledfalse 也可禁用客户端服务发现。

Eureka 安全认证

Eureka Server 提供的 Web 控制台默认是没有安全认证的,在公网上是不安全的。通过集成 Spring Security 来进行安全认证。

  1. Eureka Server 注册中心应用引入 Spring-Secruity 依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
  2. Eureka Server 注册中心应用的配置文件 application.properties 添加安全认证的账号密码

    #认证账号密码
    spring.security.user.name=admin
    spring.security.user.password=123456
    
  3. Eureka Server 注册中心应用新增 Spring Secruity 配置类

    禁用 CSRF 安全防护,否则客户端无法注册并报错。开启对所有请求要求输入账号密码进行认证。

    /**
     * @name: SpringSecurityConfig
     * @desc: SpringSecurity配置类
     **/
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity.csrf().disable()
                    .authorizeRequests().anyRequest().authenticated()
                    .and().formLogin()
                    .and().httpBasic();
    //        super.configure(httpSecurity);
        }
    }
    

    再次访问 http://localhost:8761/ ,浏览器会显示登录页面,要求输入账号密码。

  4. Eureka Client 客户端只需在配置文件 application.properties 文件的注册中心地址配置的 URL 加上账号密码即可。
    URL样式:http://user:password@localhost:8761/eureka

    #eureka 注册中心地址
    eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka
    

其它参考

  1. SpringCloud教程 | 二.Eureka常见问题总结
更多内容请访问:IT源点

全部评论: 0

    我有话说: