一、搭建项目
父工程
pom
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 pom com.badcat springCloud-demo 1.0-SNAPSHOT org.springframework.cloud spring-cloud-dependencies Greenwich.SR1 pom import org.springframework.boot spring-boot-starter-parent 2.1.5.RELEASE pom import org.projectlombok lombok 1.18.8 org.apache.maven.plugins maven-compiler-plugin 3.6.0 1.8 UTF-8
1、注册中心模块
pom
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> springCloud-demo com.badcat 1.0-SNAPSHOT ../../pom.xml 4.0.0 jar euraka-server org.springframework.cloud spring-cloud-starter-netflix-eureka-server
application.properties
spring.application.name=eureka-server server.port=20000 eureka.instance.hostname=localhost ####是否向注册中心注册,因为是单节点注册中心,所以false eureka.client.register-with-eureka=false ####拉取注册中心表,不拉取 eureka.client.fetch-registry=false
启动类(注意@EnableEurekaServer)
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @author badcat * @date 2020-03-01 10:46 */ @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
启动注册中心,访问http://localhost:20000/
2、搭建服务提供方模块
pom
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> springCloud-demo com.badcat 1.0-SNAPSHOT ../../pom.xml 4.0.0 jar eureka-client eureka-client org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web
application.properties
spring.application.name=eureka-client server.port=30000 eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/
启动类(注意@EnableDiscoveryClient)
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @author badcat * @date 2020-03-01 11:25 */ @SpringBootApplication @EnableDiscoveryClient public class EurekaClientApplication { public static void main(String[] args) SpringApplication.run(EurekaClientApplication.class, args); } }
controller
import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * @author badcat * @date 2020-03-01 11:27 */ @RestController @Slf4j public class Controller { @Value("${server.port}") private String port; @GetMapping("/sayHi") public String sayHi(){ return "this is " + port; } @PostMapping("/sayHi") public Friend sayHiPost( @RequestBody Friend friend){ log.error("you are " + friend.getName()); friend.setPort(port); return friend; } }
启动该模块,刷新刚才注册中心的页面,出现这个
调用接口试一下,两个接口都能调通
3、搭建服务消费者模块(目的是为了调用上一步骤的服务)
pom
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> springCloud-demo com.badcat 1.0-SNAPSHOT ../../pom.xml 4.0.0 eureka-consumer eureka-consume jar org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-actuator
application.properties
spring.application.name=eureka-consumer server.port=31000 eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/
启动类(注意@EnableDiscoveryClient、RestTemplate )
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * @author badcat * @date 2020-03-01 15:42 */ @SpringBootApplication @EnableDiscoveryClient public class EurekaConsumerApplication { @Bean public RestTemplate register(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class, args); } }
controller
import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; /** * @author badcat * @date 2020-03-01 15:43 */ @RestController @Slf4j public class Controller { @Autowired private LoadBalancerClient client; @Autowired private RestTemplate restTemplate; @GetMapping("/hello") public String hello(){ //获取注册中心已注册的服务 ServiceInstance instance = client.choose("eureka-client"); if (instance == null){ return "no available instances"; } String format = String.format("http://%s:%s/sayHi", instance.getHost(), instance.getPort()); log.error("url is {}", format); return restTemplate.getForObject(format, String.class); } @PostMapping("/hello") public Friend helloPost(){ ServiceInstance instance = client.choose("eureka-client"); if (instance == null){ return null; } String format = String.format("http://%s:%s/sayHi", instance.getHost(), instance.getPort()); log.error("url is {}", format); Friend friend = new Friend(); friend.setName("eureka consumer"); return restTemplate.postForObject(format, friend, Friend.class); } }
启动该模块,刷新注册中心页面
调用接口试一下
4、服务续约与剔除
服务注册方(以eureka-client模块为例)
application.properties中添加如下配置
# 每隔5秒钟,向服务注册中心发送一条续约指令 eureka.instance.lease-renewal-interval-in-seconds=5 # 如果30秒依然没有收到续约请求,判定服务过期 eureka.instance.lease-expiration-duration-in-seconds=30
注册中心
application.properties中添加如下配置(关闭自保机制,每10秒提出一次过期的服务)
# 强制关闭自保(自动开关不起作用) eureka.server.enable-self-preservation=false # 每隔多久触发一次剔除(10秒) eureka.server.eviction-interval-timer-in-ms=10000
测试剔除功能,将eureka-client的判定过期时间由30秒改为5秒、发送续约间隔由5秒改为60秒,也就是说改服务一定会过期
重启一下注册中心和eureka-client,不停刷新注册中心的那个页面,你会发现一开始eureka-client是注册成功的,几秒之后消失了。查看注册中心的控制台,发现剔除日志:
5、注册中心高可用
重新搭建两个注册中心
只贴出application.properties(注意eureka.client.service-url.defaultZone)
spring.application.name=eureka-server-peer1 server.port=20001 eureka.instance.hostname=peer1 eureka.client.service-url.defaultZone=http://peer2:40001/eureka
spring.application.name=eureka-server-peer2 server.port=40001 eureka.instance.hostname=peer2 eureka.client.service-url.defaultZone=http://peer1:20001/eureka
启动这两个注册中心,访问http://localhost:40001/,出现这个,说明成功
我们将之前的eureka-client只注册到peer1上,看看peer2上能不能也拿到eureka-client的信息
eureka-client的application.properties(注意eureka.client.serviceUrl.defaultZone是配置的20001端口,也就是peer1)
spring.application.name=eureka-client server.port=30000 eureka.client.serviceUrl.defaultZone=http://peer1:20001/eureka/
启动eureka-client,刷新http://localhost:20001/和http://localhost:40001/,两个页面都会发现eureka-client信息,说明两个peer1和peer2是相互通信的
一般来说,我们应该将eureka-client同时配置两个注册中心,所以eureka-client的application.properties应该是这个样,但是这不是同时注册到两个注册中心,而是注册到第一个可用的注册中心,然后再由注册中心来传递eureka-client的信息
spring.application.name=eureka-client server.port=30000 eureka.client.serviceUrl.defaultZone=http://peer1:20001/eureka/,http://peer2:40001/eureka/