一、单机Eureka配置(无集群)
Eureka服务端
引入依赖
注意细节:这里artifactId是 spring-cloud-starter-netflix-eureka-server 如果没有starter会报错!
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
主启动类
@SpringBootApplication
@EnableEurekaServer // 开启Eureka服务端
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class,args);
}
}
配置文件application.yml
server: # 当前模块的端口
port: 7001
eureka:
instance:
hostname: localhost # eureka服务端的实例名
client:
register-with-eureka: false # 不在注册中心注册自己
fetch-registry: false # 表示自己是注册中心,不需要检索服务
service-url:
defalult-zone: http://${eureka.instance.hostname}:${server.port}/eureka/
此时启动该spring boot模块,访问http://localhost:7001可以看到Eureka的页面
Eureka客户端
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
主启动类
@SpringBootApplication
@EnableEurekaClient // 开启Eureka客户端
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
配置文件application.yml
server:
port: 8001
spring:
application:
name: cloud-payment-service # 这里配置的name在注册入Eureka时就是的名字
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
配置完成后进入服务端页面http://localhost:7001
可以看到已经注册成功
二、配置Eureka集群
集群实现方式
集群的规则是:相互注册
这里模拟集群的话就是再创建一个Eureka模块,与先前的Eureka服务端相互注册。
一个使用7001端口,另一个使用7002端口。
两个的主要配置都是类似的(pom、主启动等)
与单机版本的区别
相互注册
这里为了模拟不同服务器之间的集群,先在windows/system32/drivers/etc中修改hosts文件:
添加两个url
两个Eureka模块进行相互注册
7001:
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com # eureka服务端的实例名
client:
register-with-eureka: false # 不在注册中心注册自己
fetch-registry: false # 表示自己是注册中心,不需要检索服务
service-url:
# 注册入另一个Eureka服务器
defaultZone: http://eureka7002.com:7002/eureka/
7002:
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com
client:
fetch-registry: false
register-with-eureka: false
service-url:
# 注册入另一个Eureka服务器
defaultZone: http://eureka7001.com:7001/eureka/
此时启动可以发现两个Eureka已经相互注册上了。
客户端注册
这里修改比较简单,只要在对应的要注册入Eureka的模块的application.yml文件中修改defaultZone,将集群的两个Eureka服务器都加入配置即可:
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 此时两个服务器都配置在defaultZone中
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
配置完成后就可以发现服务提供端注册入了两个Eureka
配置高可用服务(服务提供方集群)
做法
此处以再创建一个cloud-provider-payment模块,端口设置为8002为例:
工程内部的controller、service、dao、mapper文件等与8001保持一致(记得必须复制完全,否则出错也很难发现在哪里),需要修改的配置只有yml文件中的server.port,改为8002即可
此时完成后启动服务可以发现已经注册入了两个CLOUD-PAYMENT-SERVICE
完成这一步后,需要修改服务调用处的代码:
也就是下面的payment_url
,这里修改成注册在Eureka中的Application的名字,用来调用同一个application的不同服务端的服务。
@RestController
public class OrderController {
@Resource
private RestTemplate restTemplate;
private static final String payment_url = "http://CLOUD-PAYMENT-SERVICE";
@GetMapping("/consumer/payment/create")
public CommonResult<Integer> createPayment(Payment payment) {
return restTemplate.postForObject(payment_url+"/payment/create", payment,CommonResult.class);
}
@GetMapping("consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return restTemplate.getForObject(payment_url+"/payment/get/"+id,CommonResult.class);
}
}
但是如果只是做完这一步,直接使用http://localhost/consumer/payment/get/1
这类url在浏览器中使用会报500的错误,这是因为还没有进行负载均衡的配置。
解决的方法:给自动注入的RestTemplate加上@LoadBalanced注解,开启负载均衡(默认为轮询模式)
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
这时候借助在payment-provider模块的controller代码中的serverPort,可以发现每次使用同一个url,调用的服务端口都是不一样的:
payment-provider辅助显示当前服务端口的代码:
public class PaymentController {
@Resource
private PaymentService paymentService;
// 注入yml文件中的端口
@Value("${server.port}")
private String serverPort;
@PostMapping("/payment/create")
public CommonResult create(@RequestBody Payment payment) {
int result = paymentService.create(payment);
// 可以在返回时附带上端口号,方便在测试的时候查看是否真的进行了负载均衡
if (result == 1) {
return new CommonResult(200,"create成功 server port:"+serverPort, result);
} else {
return new CommonResult(444,"create失败");
}
}
@GetMapping("/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentService.getPaymentById(id);
if (payment != null) {
return new CommonResult(200,"查询成功 server port:"+serverPort, payment);
} else {
return new CommonResult(444,"查询失败");
}
}
}
完成服务提供者的集群与负载均衡的配置!
三、一些细节
规范在微服务中的注册:
可以看到前面的Eureka页面中,Status显示的都是主机名+名字+端口,并且鼠标移动到上面浏览器左下角不会显示该服务的ip地址等,在真正开发时,可以通过配置每一个注册模块的yml文件,使显示更加规范、清晰:
eureka:
#...前面省略,主要关注这边的instance
instance:
instance-id: consumer80 # 设置status中的名字
prefer-ip-address: true # 设置显示IP地址
给所有模块配置完成后,可以看到显示地更加清晰了: