【SpringCloud组件——Eureka】
前置准备:
分别提供订单系统(OrderService)和用户系统(UserService)。订单系统主要负责订单相关信息的处理,用户系统主要负责用户相关信息的处理。
一、微服务当中的提供者和消费者
1.1、概念
服务提供者:
一次业务中,被其它微服务调用的服务。(提供接口给其他微服务)
服务消费者:
一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
思考:服务A调用服务B,服务B又调用服务C,那么服务B是什么角色?
A调用B时,B是提供者;B调用C时,B又是消费者。这就说明,B的角色是相对的,即相对谁而言决定B的角色。在这个案例当中,B既是消费者又是提供者。
1.2、案例讲解
访问订单系统,查询订单编号为XXX的订单,并返回订单当中的用户信息。我们知道每张订单都会记录该订单支付者的信息,一般是支付者账号信息。根据该信息调用用户系统当中的根据账户查询用户的接口即可。
1.2.1、订单系统:
①、订单查询接口
@RestController
@RequestMapping("order")
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("{orderId}")public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {// 根据id查询订单并返回return orderService.queryOrderById(orderId);}
}
②、生成远程调用实例对象
//在SpringBoot启动类当中添加如下代码@Bean@LoadBalanced//负载均衡public RestTemplate restTemplatest(){return new RestTemplate();}
③、订单查询服务实现类
@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById2(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);//2.利用RestTemplate发送http请求,查询用户//2.1、url路径String url = "http://localhost:8088/user/" + order.getUserId();//2.2、发送http请求,实现远程调用User user = restTemplate.getForObject(url, User.class);//3.封装user到orderorder.setUser(user);// 4.返回return order;}
1.2.2、用户系统:
①、用户查询接口
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {return userService.queryById(id);}}
②、用户查询实现类
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User queryById(Long id) {return userMapper.findById(id);}
}
二、Eureka注册中心
我们先分析上述代码远程调用的弊端:
①、userService服务为了应对高并发,可能存在多个实例
②、userService服务可能有不同的环境配置,例如开发环境端口为8088,测试环境为8089等
③、在多实例情况下,orderService如何选择userService?
④、在多实例情况下,orderService如何知道选择的实例的健康状态?
这些弊端就足以说明我们上述硬编码方式的弊端了-》不够灵活。
2.1、Eureka的作用
当user-service:8081、user-service:8082、user-service:8083启动时会向Eureka注册中心进行登记,Eureka则会记录该服务的这些信息,同理,order-Service也会注册到Eureka当中,当orderService需要远程调用userService时,此时就会向Eureka获取该服务的注册列表,拿到注册列表后根据负载均衡原理挑选出一个服务实例进行调用。还有一个问题没有解决,Eureka如何知道某服务实例的健康状态呢?当服务实例注册到Eureka之后,会每隔30s向Eureka发送一个心跳续约,告知Eureka本实例的状态,当不发送时,Eureka则认为该实例挂掉了,则会从服务列表剔除该实例,下次当消费者再次获取实例列表时将不再推送该实例信息。智能吧?在Nacos面前这就是弟弟~
总结:
![]()
2.2、搭建Eureka注册中心
2.2.1、创建独立的服务
2.2.2、导入依赖
<dependency><groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.2.3、启动类添加注解
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class,args);}
}
2.2.4、编写配置文件
server:port: 10086 #服务端口
spring:application:name: eurekaserver #服务名称
eureka:client:service-url: #eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka
2.3、 服务注册
2.3.1、在微服务模块导入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.3.2、在微服务配置文件添加配置
spring:application:name: XXXXservice
eureka:client:service-url: #eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka
2.4、 基于Eureka远程调用
2.3完成了服务注册,下面进行后续的步骤:
2.4.1、服务列表拉取
修改访问的url路径,用服务名代替ip、端口:
String url = "http://userservice/user/" + order.getUserId();
当我们启动多个实例后 ,获取到的访问地址是该服务的实例列表,经过负载均衡算法处理过后会得到准确的访问地址。
2.4.2、做负载均衡
@Bean@LoadBalanced//负载均衡public RestTemplate restTemplatest(){return new RestTemplate();}