spring cloud学习一:服务治理框架Eureka

Eureka分为两部分

  1. 注册中心:用于维护客户端注册表。

  2. 客户端:通过注册中心获取其他客户端的注册信息表,可通过客户端负载均衡的方式访问服务实例。每个客户端即可是服务提供者,也可使服务消费者。

服务注册

客户端服务实例启动成功后,会发送一个http请求提供本身的一些信息注册中心中心,这些信息包括服务名称、ip地址、端口号、版本信息和通信协议,注册中心会将这些信息写入自己的注册表中。除此之外,注册中心还会以心跳监测的方式检查注册列表中的服务实例是否可用,需要把不可用的实例从注册表中剔除。

服务发现

在Eureka框架下,服务之间的调用不再通过指定具体的服务地址调用,而是通过服务名称来进行调用,这得益于注册表的存在。进行服务调用时,客户端会向注册中心获取注册表,实际上不会每次都会去注册中心获取,客户端本地会缓存一份,在真正进行http调用时,会通过服务名从注册表的信息中组装真正的地址,如果一个服务存在多个实例,将通过负载均衡策略访问其中的某个实例。

下面使用eureka来实现服务之间的调用,服务之间的关系如下所示:

 

搭建服务注册中心

新建一个spring boot项目,将它命名为eureka-server-demo。

修改pom.xml文件,引入Eureka server,如下所示:


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <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>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
   <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在@SpringBootApplication类中加入@EnableEurekaServer注释开启Eureka server。

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerDemoApplication.class, args);
    }

}

在application.properties文件中加入Eureka server的配置

server.port=9091

eureka.instance.hostname=localhost
#由于该服务是注册中心,所以设置不注册自己
eureka.client.register-with-eureka=false
#由于该服务是注册中心,所以设置不需要检索服务
eureka.client.fetch-registry=false
#设置注册中心的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

经过这3个步骤就可简单的配置一个单机版的Eureka注册中心了。

在浏览器中输入http://localhost:9091/ 就可以看到Eureka的注册详情。

搭建Eureka客户端(服务提供者)

新建一个spring boot项目,将它命名为eureka-service-demo,该服务扮演一个服务提供者。

修改pom.xml,如下所示:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <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>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

修改主类,加入@EnableDiscoveryClient注解。

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaServiceDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServiceDemoApplication.class, args);
    }

}

在application.properties文件中加入Eureka client的配置

server.port=9092
#服务名称,需要它来访问该服务
spring.application.name=service-demo
#服务注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:9091/eureka/

创建controller,如下所示:

@Controller
public class HelloController {
    @ResponseBody
    @RequestMapping("hello")
    public String hello(){
        return "hello";
    }
}

搭建Eureka客户端(服务消费者)

新建一个spring boot项目,将它命名为eureka-consumer-demo,该服务扮演一个服务提供者。由于要使用ribbton来进行客户端负载均衡调用服务提供者提供的服务,所以除了要引入eureka-client外,还要引入ribbton。修改pom.xml,如下所示:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在主类加入@EnableDiscoveryClient注解,声明一个RestTemplate用于使用负载均衡。如下所示:

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaConsumerDemoApplication {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(EurekaConsumerDemoApplication.class, args);
    }

}

在application.properties文件中加入Eureka client的配置

server.port=9093
#服务名称,需要它来访问该服务
spring.application.name=consumer-demo
#服务注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:9091/eureka/

增加一个controller,如下所示:

@Controller
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    @ResponseBody
    @RequestMapping("hello")
    public String hello(){
        return restTemplate.getForObject("http://SERVICE-DEMO/hello/",String.class);
    }
}

测试调用

分别运行上面3个spring boot项目,在浏览器上输入http://localhost:9091/,可用看到eureka服务注册详情界面,如下所示:

可用看到已经注册了两个服务,每个服务注册了一个实例。eureka使用服务名+端口号来区分服务实例。现在在服务器上输入http://localhost:9093/hello可以看到浏览器输入hello,comsumer服务成功调用了service服务提供的服务。

高可用的Eureka

Eureka是高可用的,允许对服务注册中心集群,实现方式是通过注册中心将自己作为服务注册到其他的注册中心。这样就可以实现一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的集群效果。

搭建服务注册中心集群

Eureka的服务端是可以进行集群的,保证高可用性。下面将搭建一个Eureka的服务端集群示例,将包含3个Eureka服务端实例。修改之前的eureka-server-demo项目。

在resurces目录下新建application-server1.properties,加入如下内容

server.port=9081
spring.application.name=eureka-server
eureka.instance.hostname=server1
#设置其他注册中心实例地址
eureka.client.serviceUrl.defaultZone=http://server2:9082/eureka/,http://server3:9083/eureka/

在resurces目录下新建application-server2.properties,加入如下内容

server.port=9082
spring.application.name=eureka-server
eureka.instance.hostname=server2
#设置其他注册中心实例地址
eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server3:9083/eureka/

在resurces目录下新建application-server3.properties,加入如下内容

server.port=9083
spring.application.name=eureka-server
eureka.instance.hostname=server3
#设置其他注册中心实例地址
eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server2:9082/eureka/

修改本地的host文件,加入如下内容,如下所示

127.0.0.1 server1
127.0.0.1 server2
127.0.0.1 server3

将eureka-server-demo打包成jar包,分别允许

java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server1
java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server2
java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server3

就启动了3个实例的注册中心集群,在浏览器中输入http://server1:9081/,可以看到详情界面,如下所示:

可以看到服务注册中心EUREKA-SERVER包含了3个实例。

之前的示例服务service-demo和cousumer-demo要注册到集群,需要修改application.properties文件,如下所示

#修改该属性
eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server2:9082/eureka/,http://server3:9083/eureka/

断开server2实例,可以看到

server2被标记为不可用,但集群仍可正常允许。只需要重启server2,server2就可以变为可用状态。

 

eureka 自我保护

当访问eureka管理界面出现如下提示,就代表eureka进入了自我保护状态。

服务注册到服务注册中心后,会和服务注册中心维持一个心跳连接来告诉服务注册中自己还活着。服务注册中心在运行期间会统计心跳失败比例是否在15分钟内是否低于85%,如果低于,会将该服务实例的信息保护起来,保证它不会过期。这种自我保护机制是有意义的,因为可能存在这种情况,服务本身没有问题,但是和服务注册中心之间的网络连接不通,这样会导致服务注册中心收不到心跳反应。然而也存在这样的情况,服务确实挂了,但服务注册中心开启了自我保护,调用该服务的服务就会获取到包含失效服务的服务清单,所有调用服务必须要有容错机制,如断路器、重试机制等。

可以通过设置eureka.server.enable-self-preservation=false来禁止该机制。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章