Eureka 集群搭建
Eureka 集群原理说明
关于EurekaServer集群
服务注册:将服务信息注册进注册中心地址
服务发现:从注册中心上获取服务信息 ,本质上,key服务名,value调用地址。
使用步骤
1、先启动eureka注册中心
2、启动服务提供者payment支付服务
3、支付服务启动后,会把自身信息(比如服务地址以别名的方式注册进入Eureka)
4、消费者Consumer服务在需要调用接口时,使用服务别名去注册中心获取实际的RPC远程调用地址
5、消费者获得调用地址后,底层利用比如HttpClient技术实现远程调用
6、消费者获得服务地址后会缓存在本地JVM内存中,默认每30s更新一次服务调用地址。
微服务RPC远程服务调用的核心是:高可用,注册中只有一个,一旦出现故障,整个系统将会崩溃,解决办法:实现负载均衡+故障容错
Eureka 集群的原理 互相注册,相互守望
Eureka 集群构建步骤
新建cloud-eureka-server7002模块
参考上节中的7001,新建cloud-eureka-server7002
小细节 修改 hots文件 mac使用命令 vim /etc/hosts 添加内容为 做一下地址映射
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
改pom.xml application.xml 和主启动类
pom.xml、application.yml 先与7001 保持一致 主启动类与7001保持相似
修改 7001 7002两个模块的 application.xml
先修改 7001的eureka.instance.hostname 修改为 eureka7001.com
service-url.defaultZone 指向 7002的地址
server:
port: 7001
# eureka 服务端的实例名称
eureka:
instance:
hostname: eureka7001.com # eureka 服务端的实例名称
client:
# false 表示不向注册中心注册自己
register-with-eureka: false
# false 表示自己就是注册中心,职责是维护服务实例,无需去检索服务
fetch-registry: false
# 设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
# 7001与7002 相互守望 相互注册
defaultZone: http://eureka7002.com:7002/eureka/
7002 的application.yml问件做相似的修改
server:
port: 7002
# eureka 服务端的实例名称
eureka:
instance:
hostname: eureka7002.com # eureka 服务端的实例名称
client:
# false 表示不向注册中心注册自己
register-with-eureka: false
# false 表示自己就是注册中心,职责是维护服务实例,无需去检索服务
fetch-registry: false
# 设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
测试
     启动 7001、7002两个模块 访问 [http://eureka7002.com:7002/](http://eureka7002.com:7002/) [http://eureka7001.com:7001//](http://eureka7001.com:7001/)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200827161338224.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dheUZlaQ==,size_16,color_FFFFFF,t_70#pic_center)
两个server 相互注册说明启动成功
8001 和 80 两个模块不需要修改 Eureka server 会复制信息到它相注册相互守望的 集群 Eureka server 中,如果不放心,可以添加 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
# eureka 相关配置文件
eureka:
client:
# 表示将自己注册进入 Eureka Server 默认为true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为true,集群时必须设置为true 才能配合 ribbon 使用 负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
80、8001 两个模块也注册进入 Eureka Server 集群
支付微服务集群配置
创建 Payment 8002 支付模块
几乎完全copy Payment 8001 flywaydb就无需拷贝了,这里模拟有多个微服务提供者,我想可以把该项目打成jar包 使用不同的端口启动,这里学习时还是和教程保持一致,原因flywaydb的版本号不一致,可能会再次执行 SQL 语句。
8002的结构如下图
修改内容
pom.xml 一致,application.xml 修改server.port
server:
port: 8002
dao service 内容不变
controller添加 本模块微服务的端口号 方便看请求的是哪一个 payment 微服务。8001 8002 两个模块controller 保持一致
package com.zjt.cloud.controller;
import com.zjt.cloud.domain.CommonResult;
import com.zjt.cloud.domain.Payment;
import com.zjt.cloud.domain.enums.CommonRestCode;
import com.zjt.cloud.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* @author zjt
* @date 2020-08-26
*/
@RestController
@RequestMapping("/payments/payment")
public class PaymentController {
@Autowired
private PaymentService service;
@Value("${server.port}")
private String port;
@PostMapping
public CommonResult<Long> create(@RequestBody Payment payment) {
long result = service.create(payment);
if (result > 0) {
return new CommonResult<>(CommonRestCode.SUCCESS, "操作成功,port:" + port, result);
} else {
return new CommonResult<>(CommonRestCode.BAD_REQUEST, null);
}
}
@GetMapping("{id}")
public CommonResult<Payment> findById(@PathVariable Long id) {
Payment payment = service.findById(id);
if (null != payment) {
return new CommonResult<>(CommonRestCode.SUCCESS, "查询成功,port:" + port, payment);
} else {
return new CommonResult<>(CommonRestCode.BAD_REQUEST, String.format("查询失败id为->%d", id), null);
}
}
}
自测测试
8002
8001
80 Consumer 模块代码修改
修改 ApplicationContextConfig使用@LoadBalanced 注解 赋予RestTemplate负载均衡的能力
package com.zjt.cloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author zjt
* @date 2020-08-26
*/
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // 使用@LoadBalanced 注解 赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
修改controller 之前为了跑通而写死的请求地址 private static final String PAYMENT_URL = “http://CLOUD-PAYMENT-SERVICE”;
package com.zjt.cloud.controllor;
import com.zjt.cloud.domain.CommonResult;
import com.zjt.cloud.domain.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author zjt
* @date 2020-08-26
*/
@Slf4j
@RestController
@RequestMapping("/consumer/payment")
public class ConsumeController {
// 先固定写死跑通
private static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Autowired
private RestTemplate template;
@GetMapping
public CommonResult<Payment> create(Payment payment) {
return template.postForObject(PAYMENT_URL + "/payments/payment", payment, CommonResult.class);
}
@GetMapping("/{id}")
public CommonResult<Payment> findById(@PathVariable Long id) {
String url = PAYMENT_URL + "/payments/payment/" + id;
log.info(url);
return template.getForObject(url, CommonResult.class);
}
}
80 模块测试
首次请求 8001 模块接收并返回数据
再次请求 8002 模块接收并返回数据