基于之前搭建的demo,和笔记验证功能。
关闭保护模式
服务注册中心:peer1开启保护模式,peer2关闭保护模式。
当我们关闭customer client时peer2将不再维护该服务实例,当peer1中还存在该服务实例。看来服务同步,不能同步这些心跳超时的服务。
使用实例名访问
在客户端程序中我们使用的是下面的访问方式,通过RestTemplate获取实例。
RestTemplate的注入
package com.demo.customer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
@Bean
@LoadBalanced
// 创建RestTemplate的spring bean实例,通过@LoadBalanced注解开启客户端均衡负载
RestTemplate restTemplate(){
return new RestTemplate();
}
}
package com.demo.customer.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/************************************************
*@ClassName : Customer
*@Description : TODO
*@Author : NikolaZhang
*@Date : 【2018/12/1 20:18】
*@Version : 1.0.0
*************************************************/
@RestController
@RequestMapping(value = "CustomerController")
public class CustomerController {
private Logger logger = LoggerFactory.getLogger(CustomerController.class);
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "ribbonCustomer", method = RequestMethod.GET)
public String ribbonCustomer(){
logger.info("-> RestTemplate Info: \n"+restTemplate.toString());
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
logger.info("->convert info: ");
for (HttpMessageConverter convert: converters) {
logger.info(convert.toString());
}
return restTemplate.getForEntity("http://bookservice/UserController/hello", String.class).getBody();
}
}
如果我们直接访问http://bookservice/UserController/hello
你会发现页面无法访问,这是因为bookservice是spring.application.name,必须解析之后才可以正确访问到我们的服务。也就是restTemplate.getForEntity("http://bookservice/UserController/hello", String.class).getBody();
注意我们的客户端必须注册到注册中心才能解析实例,否则注册中心无法向客户端发送实例清单。
所以客户端的特征为
eureka.client.fetch-register=true
且通过RestTemplate访问服务。
而服务端只需要提供客户端发现并注册服务到注册中心就好。
断开服务
断开服务之后,注册中心的实例并不会立刻清空。心跳超时后,peer2[关闭保护机制]会清理超时服务。使用客户端访问,虽然peer1仍维护该实例,但界面仍旧返回连接拒绝错误。
去掉服务端的@EnableDiscoveryClient
使用客户端访问则返回实例不可获取,No instances available for bookservice。
但是过一会控制台刷新了一条信息注册成功。之后服务正常。我想是不是因为peer1还在维护失效的服务呢?于是,关掉peer1,只开启peer2,可以看到服务中只有客户端实例。且booksysservice不可访问。
以上各位不要当真,其实吧我是把图书服务注册到了peer1上。。。。O(∩_∩)O哈哈~,不要打我。。。
当我们重启peer1,并关闭自我保护机制(此时图书服务仍不使用注解)。
控制台peer1:
控制台peer2:
界面上,peer1,2都在维护图书服务。
使用客户端访问正常。
注意此时我们服务端开启了两个,如果关掉一个呢?
有意思的事情发生了,我们的服务时而可以访问时而无实例。在心跳期间,由于实例存在,通过负载均衡,所以我们客户端会访问到失效服务。但是超时之后,实例被清除。这时我们再次刷新几次,界面都会返回一个hello给我们。
所以服务出现问题的一段时间,是最容易出现问题的时候。我们一定要弄清楚自己设置的那些间隙是多少。避免找错了问题的实质。
结束~