Eureka架构
远程调用的两个问题
服务的ip地址和端口号写死
: 生产环境中服务的地址可能会随时发生变化
,如果写死每次都需要重新修改代码多实例问题
: 在高并发的情况下一个服务可以有多个实例形成一个集群
,此时如果采用硬编码的方式只能访问服务的一个实例地址在Eureka架构中,微服务角色分为EurekaServer和EurekaClient
两类
EurekaServer(服务端)
: 可以记录服务的注册信息(包含服务名称及其相关实例地址), 对所有的服务心跳监控EurekaClient(客户端)
: Provider(服务提供者)和consumer(服务消费者)服务提供者与消费者
在服务调用关系中包含服务的提供者和服务的消费者,这两种角色的定义并不是绝对的,因为在不同业务中有些服务既可以是服务提供者也可以是服务消费者
服务提供者
:一次业务中被其他微服务调用的服务(暴露接口给其他微服务)服务消费者
:一次业务中调用其他微服务的服务(调用其他微服务提供的接口)服务消费者
在发起远程调用的时候,确定服务提供者实例的ip地址和端口号
的过程,注意服务消费者也需要把自己注册到Eureka服务端后才能使用其提供的服务
第一步服务注册
: 服务提供者实例启动后会将自己的信息注册到eureka-server(Eureka服务端)
第二步服务映射
:Eureka服务端将所有服务提供的名称和其对应的服务实例地址的映射关系保存到Map集合当中第三步服务发现
: 服务消费者根据服务提供者的名称从eureka中拉取对应信息,一个服务可能有多个服务提供者所以最终会得到一个服务实例地址列表
第四步负载均衡
: 服务消费者从实例地址列表中利用负载均衡算法选中一个实例地址并发起远程调用服务消费者如何感知服务提供者健康状态即判断服务提供者是否宕机
第一步
: 服务提供者会每隔一段时间(默认30秒)向EurekaServer服务端发送心跳请求用来报告自己的健康状态第二步
:eureka通过检查心跳请求更新服务提供者的列表信息, 发现心跳不正常就从服务列表中剔除, 这样服务消费者就可以拉取到服务提供者最新的信息搭建注册中心(EurekaServer)
第一步创建子模块: 在父工程cloud-demo中创建子模块eureka-server
,然后引入SpringCloud为Eureka提供的starter服务端依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
第二步编写启动类: 在eureka-server模块
中编写一个启动类并添加@EnableEurekaServer注解
,这样eureka-server服务
就具有了作为注册的中心功能
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class);
}
}
第三步编写配置文件: 在eureka-server服务
中将它自己的服务名称和相关的实例地址信息注册到eureka-server服务上,便于和其他eureka集群之间的通信
server:
port: 10086 # 服务端口
spring:
application:
name: eureka-server # eureka的服务名称
# eureka服务将自己的信息注册到Eureka服务端
eureka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
第四步:启动微服务然后在浏览器访问http://localhost:10086/
服务注册
第一步引入依赖: 在user-service,order-service模块
的pom.xml文件中引入Eureka的客户端依赖spring-cloud-starter-netflix-eureka-client
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
第二步服务注册: 在user-service,order-service模块
的application.yml中配置自己的服务的名称
和eureka-server服务的地址信息
spring:
application:
name: userservice # 服务名称
# userservice服务将自己的信息注册到Eureka服务端
eureka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
spring:
application:
name: orderservice # 服务名称
# orderservice将自己的信息注册到Eureka服务端
eureka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
第三步模拟多实例部署: 在IDEA中复制一份user-service实例
的配置重新设置Name同时配合VM选项修改端口号-Dserver.port=8082
多次启动
第四步: 查看Eureka服务端注册的服务及其相关的所有实例
服务发现
第一步引入依赖: 服务发现和服务注册统一都封装在Eureka的客户端依赖中,如果注册时已经引入了该依赖就不用重复引入了
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
第二步服务发现:只要orderservice服务
注册到eureka-server服务
中就可以拉取userservice服务
的实例地址列表
orderservice模块
的启动类中给注册的RestTemplate
这个Bean上添加一个负载均衡的注解@LoadBalanced
order-service模块
的OrderService类中的queryOrderById方法
中远程调用的访问路径中使用服务名(userservice)代替服务实例的ip和端口
userservice
这个服务名称获取对应的实例地址列表,然后利用负载均衡算法选中一个实例地址并发起远程调用@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.调用userservice服务远程查询User,使用服务的名称代替服务的IP地址和端口
//String url = "http://localhost:8081/user/" + order.getUserId();
String url = "http://userservice/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);
// 3.存入查询到的user对象
order.setUser(user);
// 4.返回
return order;
}