服务治理
Spring Cloud 封装了 Netflix公司开发的 Eureka 模块来实现服务治理。
在传统的rpc远程调用框架中,管理每个服务于服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
假如我们的服务提供者user-service部署了多个实例,如图:
思考几个问题:
- order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
- 有多个user-service实例地址,order-service调用时该如何选择?
- order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
Eureka的结构和作用
上面这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:
服务提供者和服务消费者实例启动后,都会将自己的信息注册到Eureka注册中心。这个叫服务注册。Eureka保存服务名称到服务实例地址列表的映射关系。
服务消费者,想要某个服务,就去Eureka注册中心请求,注册中心发现有这个服务,就把这个服务的列表给消费者。
而消费者从Eureka获取的服务地址列表中通过负载均衡算法选中一个实例地址,向该实例地址发起远程调用。
每个服务都会每隔一段时间(默认30秒)向Eureka注册中心发起请求,报告自己的状态,这种称为心跳。当超过一定时间没发送心跳时,Eureka会认为该服务实例故障,将该实例从服务列表中剔除。当消费者拉服务的时候就能排除故障了。搭建Eureka注册中心
SpringCloud服务搭建,拆分,调用Demo
根据这个demo,添加一个module,springboot项目。
- 引入依赖,没写版本号是因为之前的demo父模块里面有版本号
老版本引入的eureka服务端依赖为:spring-cloud-starter-eureka 新版本使用的eureka服务端依赖为:spring-cloud-starter-netflix-eureka-server
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
- 启动类上加注解
@EnableEurekaServer启动Eureka服务的功能 ```java package cn.itcast.eureka;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
3. 编写配置文件```yamlserver:port: 10086spring:application:name: eureka-servereureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
最后启动了这个服务后,访问地址http://localhost:10086/就能看到Eureka的管理页面
服务注册
给需要注册服务的消费者或者提供者 引入依赖和改配置文件。
demo例子,我们给user-service和order-service注册一下。拿user-service举例子。
引入依赖,eureka那个是服务端,这个是客户端,注意后面的结尾,还有上面提到的新老版本
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
修改application.yml文件,添加服务名称、eureka地址:
spring:application:name: userserviceeureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
就这两步弄完了就重新启动服务就行了
同一个服务启动多个实例
我们模拟启动两次以上user-service服务。
在左下角服务窗格里面选中右键:
不一样的名字,还有设置新的端口-Dserver.port=9081
全部服务重新运行后访问,Eureka的地址就能看到注册的实例了
服务发现
下面,我们将order-service的逻辑修改:向eureka-server拉取user-service的信息,实现服务发现。
- 引入依赖
服务发现、服务注册统一都封装在eureka-client依赖,因此这一步与服务注册时一致。在order-service的pom文件中,引入下面的eureka-client依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
- 配置文件
服务发现也需要知道eureka地址,因此第二步与服务注册一致,都是配置eureka信息:在order-service中,修改application.yml文件,添加服务名称、eureka地址
spring:application:name: orderserviceeureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
- 负载均衡
在配置文件中RestTemplate上在一个注解@LoadBalanced实现负载均衡
package cn.itcast.order.config;@Configurationpublic class MyConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}}
- 修改业务代码,修改访问的url路径,用服务名代替ip+端口。这样就能访问到用户数据了 ```java package cn.itcast.order.service;
@Service public class OrderService {
@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DataSource druidDataSource;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.远程查询user localhost:8081String url = "http://userservice/user/"+order.getUserId();User user = restTemplate.getForObject(url, User.class);// 3.组合order.setUser(user);// 4.返回return order;}
}
```
