SpringCloud如何实现服务治理

Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。

zookeeper和eureka比较

  • Eureka 保证APEureka中各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时如果发现连接失败,则会自动切换至其它节点,从而保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

    • Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。

    • Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)。

    • 当网络稳定时,当前Eureka新的注册信息会被同步到其它节点中。 Eureka还有客户端缓存功能

  • Zookeeper 保证CP 当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。在选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。

动手搭服务发现和注册

第一步:创建服务注册中心

创建Spring boot项目,命名为eureka-server,并在pom.xml中引入需要的依赖内容:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
​
<!-- 引入Eureka服务包-->
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
</dependencies>
​
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • 通过 @EnableEurekaServer 注解启动一个服务注册中心提供给其他应用进行对话。在Spring Boot启动类加上这个注解即可,如下:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
  • 在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.properties配置文件中增加如下信息:

spring.application.name=eureka-server
server.port=1111
eureka.client.service-url.defaultZone=http://127.0.0.1:${server.port}/eureka
#表示是否将自己注册到Eureka Server上,默认为true
eureka.client.registerWithEureka=false
#表示是否从Eureka Server上获取注册信息,默认为true
eureka.client.fetchRegistry=false
  • 启动工程,访问 http://localhost:1111/ ,可以看到下面的页面,其中还没有发现任何服务。

第二步:创建服务提供方

下面我们创建提供服务的客户端,并向服务注册中心注册自己。本文我们主要介绍服务的注册与发现,所以我们不妨在服务提供方中尝试着提供一个接口来获取当前所有的服务信息。

假设我们有一个提供计算功能的微服务模块,我们实现一个RESTful API,通过传入两个参数a和b,最后返回a + b的结果。

首先,创建一个基本的Spring Boot应用,在pom.xml中,加入如下配置:

  • 首先,创建一个基本的Spring Boot应用。命名为eureka-order,在pom.xml中,加入如下配置:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
​
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
​
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

其次,实现/add请求处理接口,通过DiscoveryClient对象,在日志中打印出服务实例的相关内容。

@RestController
public class ComputeController {
​
    private final Logger logger = Logger.getLogger(getClass());
​
    @Autowired
    private DiscoveryClient client;
​
    @RequestMapping(value = "/add" ,method = RequestMethod.GET)
    public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
        ServiceInstance instance = client.getLocalServiceInstance();
        Integer r = a + b;
        logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
        return r;
    }
}

最后在主类中通过加上 @EnableDiscoveryClient注解,该注解能激活Eureka中的DiscoveryClient实现,才能实现Controller中对服务信息的输出。

@SpringBootApplication
@EnableEurekaClient
public class EurekaOrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaOrderApplication.class, args);
    }
}
  • 我们在完成以上工作后,再继续对eureka-order的application.properties做一些配置工作,具体如下:

spring.application.name=eureka-order
server.port=2222
eureka.client.service-url.defaultZone=http://127.0.0.1:1111/eureka

通过spring.application.name属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问。eureka.client.serviceUrl.defaultZone属性对应服务注册中心的配置内容,指定服务注册中心的位置。为了在本机上测试区分服务提供方和服务注册中心,使用server.port属性设置不同的端口。