小言_互联网的博客

Spring Cloud(13)——服务注册与发现工具Consul

430人阅读  评论(0)

服务注册与发现工具-Consul

Spring Cloud也可以使用Consul作为服务注册与发现工具。Consul和Eureka一样,也有服务端和客户端的概念,它们都需要基于Consul Agent运行,即Agent有Server模式和Client模式,开发环境可以直接通过consul agent -dev启动一个Agent,它默认会监听8500端口。

注册服务

作为服务提供方如果需要通过Consul注册服务,则需要在应用中添加spring-cloud-starter-consul-discovery依赖。

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

另外我们的应用需要通过http提供服务,所以还需要加上spring-boot-starter-web依赖。

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

不需要加其它特殊的配置了。服务启动后会自动向本机的8500端口发起服务注册请求。注册的服务名将取${spring.application.name},端口号取${server.port}

@SpringBootApplication
public class Application {

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

}

所以当我们在application.properties中定义了如下配置后,注册的服务名是spring-cloud-consul-server,传递的端口号是9100。

server.port=9100
spring.application.name=spring-cloud-consul-server

如果Consul Client的host不是localhost或者port不是8500,则可以通过如下方式进行指定。比如下面指定了Consul Client的主机地址是10.10.10.3,端口号是8501。

spring.cloud.consul.host=10.10.10.3
spring.cloud.consul.port=8501

注册服务时默认会传递当前主机的主机名,如果希望使用IP,则可以指定spring.cloud.consul.discovery.prefer-ip-address=true。此时注册到Consul的当前服务的主机就会改用当前主机的IP地址,比如当前服务的主机IP地址是10.10.10.1,服务端口号是8080,则注册到Consul的服务主机地址是10.10.10.1,客户端就可以通过http://10.10.10.1:8080/xxx访问到当前服务。

spring.cloud.consul.discovery.prefer-ip-address=true

可以通过spring.cloud.consul.discovery.enabled=false来禁用Consul。

服务发现

服务发现是针对于客户端来说的,服务端注册了服务后,客户端可以通过Consul获取服务端的地址。作为客户端的一方也需要加入spring-cloud-starter-consul-discovery依赖,但是它通常不需要向Consul注册服务,所以通常我们需要定义spring.cloud.consul.discovery.register=false以关闭自动向Consul注册服务。

直接通过DiscoveryClient获取

可以直接通过Spring Cloud抽象的org.springframework.cloud.client.discovery.DiscoveryClient来获取某个服务的地址。下面的代码中就直接注入了DiscoveryClient,然后通过它获取到了服务spring-cloud-consul-server的相关实例信息。

@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class DiscoveryClientTest {

  private final String serviceId = "spring-cloud-consul-server";

  @Autowired
  private DiscoveryClient discoveryClient;

  @Test
  public void test() {
    List<String> serviceIds = this.discoveryClient.getServices();
    Assert.assertTrue(serviceIds.contains(serviceId));

    List<ServiceInstance> instances = this.discoveryClient.getInstances(serviceId);
    Assert.assertEquals(9100, instances.get(0).getPort());

  }

}

通过Ribbon获取

当存在Ribbon的依赖时,比如spring-cloud-starter-netflix-ribbon,可以通过RestTemplate来访问Consul上注册的服务。RestTemplate可以利用Ribbon进行客户端的负载均衡,下面的代码中定义了org.springframework.web.client.RestTemplate类型的bean,而且加上了@LoadBalanced,表明该RestTemplate拥有了基于Ribbon的负载均衡能力。

@SpringBootApplication
public class Application {

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

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

}

然后就可以像下面这样在需要使用RestTemplate的地方注入RestTemplate,调用某个具体的服务时就可以不用指定服务主机地址了,改为使用serviceId,即之前注册服务时定义的服务名称,比如下面的spring-cloud-consul-server。下面就调用了服务spring-cloud-consul-server/hello,返回的是一串hello worldXXX

@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class RestTemplateTest {

  private final String serviceId = "spring-cloud-consul-server";

  @Autowired
  private RestTemplate restTemplate;

  @Test
  public void test() {
    String url = "http://" + serviceId + "/hello";
    String result = this.restTemplate.getForObject(url, String.class);
    Assert.assertTrue(result.startsWith("hello world"));

    ResponseEntity<String> responseEntity = this.restTemplate.getForEntity(url, String.class);
    Assert.assertEquals(200, responseEntity.getStatusCodeValue());
    Assert.assertTrue(responseEntity.getBody().startsWith("hello world"));
  }

}

通过Feign访问

Feign底层也是使用的Ribbon进行负载均衡的,如果需要整合使用Feign和Consul,可以在客户端工程中加上feign的依赖。

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

其它操作就和之前介绍的基于Eureka进行服务发现使用Feign的方式是一样的。先在@Configuration类(通常是启动类Application)上加上@EnableFeignClients以启用FeignClient。

@SpringBootApplication
@EnableFeignClients
public class Application {

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

}

然后就可以定义自己的FeignClient了,如下面代码中定义了一个HelloService接口,接口上使用@FeignClient指定了对应的服务名称是${feign.client.hello}(占位符,可以在application.properties中通过feign.client.hello属性名指定真正的服务名)。

@FeignClient("${feign.client.hello}")
public interface HelloService {

  @GetMapping("/hello")
  String hello();

}

上面的HelloService会被扫描到并注册为一个Spring bean,可以在其它地方进行注入使用。

关于Feign的其它配置信息可以参考之前写的一篇专门介绍Feign的文章。

整合Hystrix

单纯的Hystrix的使用是与Consul无关的,即无论服务提供方以何种方式注册服务,其都可以使用Hystrix进行熔断。但是当我们的服务提供方使用了Consul进行服务注册后,在通过Turbine进行服务的熔断信息监控时,我们的Turbine应用也需要基于Consul获取服务信息。

服务提供方

服务提供方使用Hystrix时需要在pom.xml中添加如下依赖,spring-cloud-starter-netflix-hystrix是为了引入Hystrix的支持,spring-boot-starter-actuator是为了获取监控信息的。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

对应的监控信息由hystrix.stream这个Endpoint发布,所以还需指定management.endpoints.web.exposure.include=hystrix.stream以对外发布hystrix.stream,从而可以收集到Hystrix的相关信息。

然后需要在配置类上加上@EnableHystrix以启用Hystrix的支持。

@SpringBootApplication
@EnableHystrix
public class Application {

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

}

然后就可以在需要进行断路器控制的方法上加上@HystrixCommand了。

@GetMapping("{times}")
@HystrixCommand(fallbackMethod = "sayHelloTimesFallback")
public String sayHelloTimes(@PathVariable("times") int times) {
Preconditions.checkArgument(times % 3 != 0);
  return "hello times: " + times + "----" + LocalDateTime.now();
}

public String sayHelloTimesFallback(int times) {
  return "hello times from callback: " + times + "----" + LocalDateTime.now();
}

Turbine应用

对于Turbine应用因为需要使用Consul进行服务发现,所以首先需要加上spring-cloud-starter-consul-discovery依赖。然后是Web应用,需要加上spring-boot-starter-web。Turbine支持需要加上spring-cloud-netflix-turbine。Hystrix的Dashboard需要加上spring-cloud-starter-netflix-hystrix-dashboard依赖。

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

然后需要在配置类上加上@EnableTurbine以启用Turbine,加上@EnableHystrixDashboard以启用Hystrix的Dashboard。

@SpringBootApplication
@EnableTurbine
@EnableHystrixDashboard
public class Application {

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

}

然后需要在application.properties文件中配置需要聚合的服务的信息。

turbine.aggregator.cluster-config=spring-cloud-consul-server
turbine.app-config=spring-cloud-consul-server

假设Turbine应用部署的端口号是9102,接着访问http://localhost:9102/hystrix可以看到如下Hystrix Dashboard。

然后在输入框中输入http://localhost:9102/turbine.stream?cluster=spring-cloud-consul-server后点击下面的监控按钮就可以查看到服务spring-cloud-consul-server的Hystrix相关信息了,比如下面这样。

(注:本文是基于Spring Cloud Finchley.SR1所写)


转载:https://blog.csdn.net/elim168/article/details/101569784
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场