目录
[1、Eureka 原理分析](#1、Eureka 原理分析)
[2、Eureka 服务搭建(注册 eureka 服务)](#2、Eureka 服务搭建(注册 eureka 服务))
[3、Eureka 服务注册(注册其他服务)](#3、Eureka 服务注册(注册其他服务))
[4、Eureka 服务发现(服务拉取)](#4、Eureka 服务发现(服务拉取))
[三、Ribbon 负载均衡](#三、Ribbon 负载均衡)
一、服务拆分
通过 2 个案例,学习如何实现服务拆分。
- 都需要引入 web 的起步依赖:

1、案例一:多端口微服务
需求:
- 将 Order 和 User 模块的服务进行拆分,通过不同的 URL 进行服务调用。
(1)项目结构
- 为 2 个模块都添加上各自的 Controller;

(2)编写 Controller
- 写一个简单的 Controller,在页面上显示字符串即可;
- UserController 类似;

(3)设置不同的端口,启动 application
- 为两个模块设置不同的服务器端口(user 设置 8081、order 设置 8080);

- 将 Order 模块和 User 模块的 Application 都启动起来;

- 访问页面 /user/query 和 /order/query

2、案例二:服务远程调用
需求:
- 在 Order 的实体类中包含了 User 类型的属性,当根据订单号获取订单信息时,由于 Order 和 User 的数据库访问也是独立的,导致 User 属性为 null。
- 因此在 Order 模块中需要调用 User 模块的查询 user 的功能来获取 User 信息,再赋值给 Order。
(1)项目结构
- 两个模块都需要创建对应的实体类;
- Order 还需要创建 service 和 mapper;

(2)OrderController 和 UserController
- 两个模块的 Controller 都需要添加相应的方法;


(3)OrderMapper
- 为了简单起见,这里不引入连接数据库操作;
- 直接在 mapper 中实现返回一个 User 的方法;

(4)OrderSrevice
OrderSrevice 需要两个属性:OrderMapper 和 RestTemplate;
其中 RestTemplate 就是帮助我们实现远程服务调用的关键;
- url 属性:表示发送的请求;
- responseType 属性:表示返回的数据类型(默认是 JSON);
- getForObject() 方法:表示发送 get 请求;
- postForObject() 方法:表示发送 post 请求;

(5)启动两个模块的 application
- 访问 /order/queryForOrderById/xxx;

二、Eureka
1、Eureka 原理分析
观看下面视频:
2、Eureka 服务搭建(注册 eureka 服务)
(1)创建 eureka 服务模块(eureka 为子工程)
- 子工程的 pom 文件中引入依赖;

- 父工程的 pom 文件做好依赖管理;

(2)编写 application 配置文件,注册 eureka
- 设置服务端口;
- 设置 eureka 服务名称;
- 设置 eureka 服务地址;

为什么 eureka 自身的服务地址信息也是 client?
- eureka 也是一个微服务,所以 eureka 启动的时候,会将自己也注册到 eureka 上。
- 这是为了 eureka 之间的集群通信,当有多个 eureka 时,defaultZone 就需要写上多个 URL。
(3)启动 application,访问 eureka
- 为启动类添加 @EnableEurekaServer 注解;

- 访问 localhost:10086/eureka,则会跳转到 eureka 的管理界面;

- instances 表示注册到 eureka 的服务示例(服务列表);

3、Eureka 服务注册(注册其他服务)
(1)引入依赖
- 分别在 Order 模块和 User 模块的 pom 文件中,都添加上如下依赖;
- 注意:使用的是客户端 client 的依赖;

(2)编写 eureka 地址信息
这一步骤跟前面的是一样的。
- 设置服务端口;
- 设置 eureka 服务名称;
- 设置 eureka 服务地址;

(3)将 User 和 Order 的 application 都启动
- 在 Service 中添加 SpringBoot 服务,即可一次性启动;

- 访问 /localhost:10086,来到 eureka 管理页面;
- 此时已经可以看到服务列表已经有 3 个服务了;

(4)多实例部署
如果我们想要 User 有多个服务实例可以添加到服务列表上,可以复制多几份 User 的运行配置。
- 选中要复制的运行配置,点击复制;

- 在 VM Option 中,添加参数 server.port = 一个没用过的端口;

- 启动 5 个 application,观察服务列表;

- 可以发现,Order 和 User 各多了 1 个服务;

4、Eureka 服务发现(服务拉取)
服务发现就是服务拉取。
服务拉取是基于服务名称获取服务列表 (比如获取 UserService 的服务列表,内含 2 个服务),然后在对服务列表做负载均衡。
基于前面"服务拆分 "的"案例二:服务远程调用",我们来学习服务拉取。
(1)获取服务列表
- 修改 OrderService 中的代码,用服务名代替 ip:port;
- (既然需要负载均衡,因此肯定无法指定 ip:port,所以使用服务名代替)

(2)添加负载均衡注解 @LoadBalanced
- 在 order-service 项目的启动类 OrderApplication 中的 RestTemplate 添加负载均衡注解:

(3)启动 application,查询 Order
- 启动下面 5 个 application;
- 然后我们选择使用 8080 端口的 Order 来获取信息(也可以用 8083 的);

- 发送 4 次获取 Order 信息的请求,id 从 1~ 4;

- 观察 2 个 User 启动类的输出,都输出了 2 次信息;
- 说明对 user-service 服务列表做到了负载均衡;


三、Ribbon 负载均衡
Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡的工具。
它可以在客户端的 application 配置文件中,配置 RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟 http 请求,但是步骤比较繁琐。
1、负载均衡原理

2、负载均衡策略
Ribbon 的负载均衡规则是一个叫做 IRule 的接口来定义的,每一个子接口都是一种规则。
(1)Java 可以使用的负载均衡规则

(2)负载均衡规则修改方法
默认情况下,使用的是 ZoneAvoidanceRule。

需要注意的是:
- 第一种方式,可以对所有 order-service 模块访问的服务列表做到负载均衡;(大)
- 第二种方式,只能对配置文件中指定的 service 做到负载均衡;(小)
3、饥饿加载
Ribbon 默认是采用懒加载,即第一次访问时才会去创建 LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

- enabled = true,表示开启饥饿加载;
- clients = user-service,表示指定对 user-service 这个服务饥饿加载;
- clients 其实是数组形式,可以协商多个服务;