目录
微服务——远程调用
由于遵序微服务中不同服务不能开发相同功能的原则,所以当服务A需要用的服务B的数据时,就应该由服务A直接去调用服务B而不是由用户向A发送一个请求后,在向B发送一个请求。
而RestTemplate就是用来解决一个服务向另一个服务发送请求的类
具体用法
需求
现在我们有两个服务order-service和user-service。端口号分别为8080和8081
前者用来查询订单,后者用来管理用户。但是订单实体类包含用户属性。如下
所以在我们查询订单时应该根据userID查询访问用户服务的接口来获取用户对象为user属性赋值
实现
首先我们应该在需要用到远程调用的spring启动类中创建RestTemplate并注入spring容器,如下:
package cn.itcast.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 创建RestTemplate并注入spring容器
* @return
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
然后在Service层进行订单查询时进行服务调用为user赋值
@Service
public class OrderService {
@Autowired(required = false)
private OrderMapper orderMapper;
/**
* spring提供了一个工具——RestTemplate做服务与服务之间的调用
* 注入RestTemplate
*/
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2、利用RestTemplate发送http,查询用户
//2.1 url路径
String url = "http://localhost:8081/user/"+order.getUserId();
//2。1 发送http请求,实现远程调用
//getForObject第一个参数是url路径,第二个是返回的class类型
User user = restTemplate.getForObject(url, User.class);
//3.封装user到Order
order.setUser(user);
// 4.返回
return order;
}
}
Eureka注册中心
假如我们的服务提供者user-service部署了多个实例,如图:
就出现了如下问题:
-
order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
-
有多个user-service实例地址,order-service调用时该如何选择?
-
order-service如何得知某个user-service实例是否依然健康,服务是不是已经挂掉?
Eureka的结构
这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:
回答以上前的各个问题。
问题1:order-service如何得知user-service实例地址?
获取地址信息的流程如下:
-
user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册
-
eureka-server保存服务名称到服务实例地址列表的映射关系
-
order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
问题2:order-service如何从多个user-service实例中选择具体的实例?
-
order-service从实例列表中利用负载均衡算法选中一个实例地址
-
向该实例地址发起远程调用
问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
-
user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
-
当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
-
order-service拉取服务时,就能将故障实例排除了
注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端
搭建eureka-server
首先大家注册中心服务端:eureka-server,这必须是一个独立的微服务,要创建一个新的module
引入eureka依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
编写启动类(就是普通的springBoot启动类)
package com.neusoft.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
编写配置文件(yml)
server:
port: 10086
spring:
application:
name: eurekaserver # 服务名称
eureka:
client:
service-url: # eureka地址信息,因为他自己也是个微服务,启动时把自己也注册在eureka中,做eureka集群,多个以逗号隔开
defaultZone: http://127.0.0.1:10086/eureka/
register-with-eureka: false
在把user_service注册进入Eureka
在uesrservice的pom中添加依赖
然后在yml中配置eureka,除了定义服务自己的名称之外,与搭建eureka时无差别,因为eureka配置也是把自己当成一个服务注册到注册中心中
最后
在service窗口启动此服务,并点击蓝色区域
老版ider可能没有service或者图片中的窗口,开启方法参考如下
老版IDEA如何开启Services运行窗口_小厂程序员DHJ的博客-CSDN博客_idea打开运行窗口经常给同事看问题,调BUG就发现,他们IDEA的Services运行窗口特别好用,方便。可以直观地看到本项目所有能启动的Application以及其占用的端口,对于经常改配置文件的微服务项目来说,可太方便了。较新版本的IDEA直接在View -> Tool Windows中就能找到Service(Alt+F8)。我的IDEA是2018.02版本的没有,没有找到,需要做点配置。...https://blog.csdn.net/qq_41057885/article/details/122539605
点击后如图:
因为eureka的yml配置了 register-with-eureka: false 表示禁止自己当做服务注册
所以只能看见USERSERICE
扩展 开启两个相同服务实例
找到要copy的服务右键
点击apply就可以看到copy的实例了
运行如图: