导航
[封装01-设计模式] 设计原则 和 工厂模式(简单抽象方法) 适配器模式 装饰器模式
[封装02-设计模式] 命令模式 享元模式 组合模式 代理模式
[React 从零实践01-后台] 代码分割
[React 从零实践02-后台] 权限控制
[React 从零实践03-后台] 自定义hooks
[React 从零实践04-后台] docker-compose 部署react+egg+nginx+mysql
[React 从零实践05-后台] Gitlab-CI使用Docker自动化部署
[源码-webpack01-前置知识] AST抽象语法树
[源码-webpack02-前置知识] Tapable
[源码-webpack03] 手写webpack – compiler简单编译流程
[源码] Redux React-Redux01
[源码] axios
[源码] vuex
[源码-vue01] data响应式 和 初始化渲染
[源码-vue02] computed 响应式 – 初始化,访问,更新过程
[源码-vue03] watch 侦听属性 – 初始化和更新
[源码-vue04] Vue.set 和 vm.$set
[源码-vue05] Vue.extend
[源码-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue项目
[部署03] gitlab-CI
[深入01] 执行上下文
[深入02] 原型链
[深入03] 继承
[深入04] 事件循环
[深入05] 柯里化 偏函数 函数记忆
[深入06] 隐式转换 和 运算符
[深入07] 浏览器缓存机制(http缓存机制)
[深入08] 前端安全
[深入09] 深浅拷贝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模块化
[深入13] 观察者模式 发布订阅模式 双向数据绑定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手写Promise
[深入20] 手写函数
[深入21] 数据结构和算法 – 二分查找和排序
[深入22] js和v8垃圾回收机制
[深入23] JS设计模式 – 代理,策略,单例
[前端学java01-SpringBoot实战] 环境配置和HelloWorld服务
[前端学java02-SpringBoot实战] mybatis + mysql 实现歌曲增删改查
[前端学java03-SpringBoot实战] lombok,日志,部署
[前端学java04-SpringBoot实战] 静态资源 + 拦截器 + 前后端文件上传
[前端学java05-SpringBoot实战] 常用注解 + redis实现统计功能
[前端学java06-SpringBoot实战] 注入 + Swagger2 3.0 + 单元测试JUnit5
[前端学java07-SpringBoot实战] IOC扫描器 + 事务 + Jackson
[前端学java08-SpringBoot实战总结1-7] 阶段性总结
[前端学java09-SpringBoot实战] 多模块配置 + Mybatis-plus + 单多模块打包部署
[前端学java10-SpringBoot实战] bean赋值转换 + 参数校验 + 全局异常处理
[前端学java11-SpringSecurity] 配置 + 内存 + 数据库 = 三种方式实现RBAC
[前端学java12-SpringSecurity] JWT
[前端学java13-SpringCloud] Eureka + RestTemplate + Zuul + Ribbon
(一) 前置知识
(1) 一些单词
assistant 助理
framework 框架 架构
replica 复制品 摹本
discovery 发现
ribbon 丝带
balance 平衡 均衡 // @LoadBalanced // 声明一个基于Ribbon的负载均衡
复制代码
(2) 单体应用存在的问题
- 随着业务越来越复杂,系统会越来越庞大
一个模块出现问题,很可能造成整个业务系统崩溃
- 多个团队对数据进行管理,容易产生安全漏洞
- 各个模块都使用同一种技术,很难根据实际情况选择更适合的技术框架,局限性很大
- 模块内容太复杂,成员变动需要很长时间才能完成工作交接
(3) ( 分布式 ) 和 ( 集群 )
- 集群
- ( 一台服务器 ) 无法负荷 ( 高并发的数据访问量 ),那么就用 ( 十台 ) 来 ( 分摊压力 )
- 物理层面
- 分布式
- 将一个复杂的问题拆分成多个简单的小问题
- 将一个 ( 大型的项目 ) 拆分成 ( 若干个微服务 ) 来 ( 协同完成 )
- 软件设计层面
(4) 架构
- spring cloud 架构图
- 组件
- 注册中心 Eruka
- 负载均衡 Ribbon
- 监控 Zipkin
- 网关 zuul
- 等
(二) Spring Cloud
(1) 注册中心 Eureka
- eureka 是发现了的意思
- 注册中心也叫服务中心
- 注册中心的作用
- ( 注册中心 ) 上保存的是 ( 服务名 )
- ( 已注册的服务 ) 可以通过 eureka 来获取 ( 其他服务的服务名 ),通过服务名来完成远程调用,这样 ( 某个服务换了IP ) 也不用在意,名字不变就行
- 有了注册中心,任何一个服务都不能直接去调用,都需要通过注册中心来调用
- 总结
- (
Eureka
) 主要作用是 (服务注册
) 和 (服务发现
) - (
Eureka
) 涉及到 (服务提供者provider
) 和 (服务消费者consumer
)
- (
(1.1) Eureka 基本架构
- Eureka
Server
- 提供 服务注册 和 服务发现
- Service
Provider
- 服务提供方
- 将自身的服务注册到Eureka,从而使消费方能找到
- Service
Consumer
- 服务消费方
- 从Eurkea获取注册服务列表,从而能够消费服务
(三) 在srpingboot中使用spring cloud/Eureka
- spring-cloud官网
- 实战项目源码
- 以 eureka 注册中心为例
- 注册中心 server
- 服务提供者 client
(1) 新建父工程
- 父工程可以选择 ( Spring-Assistant ) 快速创建一个web服务工程,父工程中具有
- spring-boot-starter-web
- spring-boot-start-test
(2) 在父工程的pom.xml中添加springcloud相关的maven依赖
<properties>
<!-- spring cloud 版本-->
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<!-- 子模块需要显示的声明引用的模块,对包进行统一管理 -->
<!-- spring-cloud-dependencies -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
(3) 新建一个module,取名eurekaServer,修改子module的pom.xml
- eureka 是注册中心,负责注册服务和提供服务等
- 下面的pom.xml表示eurekaServer是注册中的server
在子module - eurekaServer 的pom.xml文件中添加
---
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
复制代码
(4) 在子module-eurekaServer的resources中添加application.yml配置文件
eurekaServer/resources/application.yml
---
server:
port: 8761
eureka:
client:
register-with-eureka: true # 是否注册自己,即是否将当前的 eureka server 作为client进行注册
fetch-registry: false # 是否获取其他 eureka server 服务数据
service-url:
defaultZone: http://localhost:8761/eureka/ # 注册中心的访问地址
复制代码
(5) 在 eurekaServer 中添加启动类,并添加 @EnableEurekaServer 注解
@SpringBootApplication // springboot 服务入口启动类
@EnableEurekaServer // 声明该类是一个 eureka server 微服务,提供服务注册和服务发现功能,即注册中心
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
复制代码
(6) 从1-5步有一个 ( 巨坑
),就是要保证 ( springBoot
) 和 ( springCloud
) 的 ( 版本要一致
),不然会报错启动不了
(7) 启动 eurekaServer,访问在在application.yml中声明的配置中心地址
- 访问:
http://localhost:8761
- 因为这里 注册中心 还没有注册任何服务,所以开启对自己的注册
- 即
egister-with-eureka: true
- 服务开启:
up
- 服务关闭:
down
- 即
- 开启中,效果如下
(8) 有了配置中心,我们新建 eurekaClient 来提供服务
- 新建module => eurekaClient
- 在 eurekaClient 模块中的 pom.xml 中做如下配置
- 在 eurekaClient 模块中的 application.yml 中配置client
- 在 eurekaClient 模块中新建启动类 EurekaClientApplication
1. eurekaClient/pom.xml
---
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
复制代码
2. eurekaClient/resources/application.yml
---
server:
port: 8761
eureka:
client:
register-with-eureka: true # 是否注册自己,即是否将当前的 eureka server 作为client进行注册
fetch-registry: false # 是否获取其他 eureka server 服务数据
service-url:
defaultZone: http://localhost:8761/eureka/ # 注册中心的访问地址
复制代码
3. eurekaClient/java/com/example/eurekaClient/EurekaClientApplication
---
@SpringBootApplication
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
复制代码
- 访问效果如下
(四) RestTemplate
- RestTemplate 是Spring框架提供的REST的服务组件,底层是对http请求和响应进行了封装,提供了访问ERST服务的方法,来简化代码开发
- 这里需要注意一点
就是通过RestTemplate连接的调用方不必在注册中心注册,因为调用服务谁都可以调用
(1) 继续创建子module – restTemplate – 然后创建启动类
- RestTemplateApplication
resTemplate/java/com.example.restTemplate/RestTemplateApplication
---
@SpringBootApplication
public class RestTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(RestTemplateApplication.class, args);
}
@Bean // 注册到容器中,则在别的类中可以通过@AutoWired注入
public RestTemplate restTemplate() {
return new RestTemplate(); // 返回 RestTemplate 的实例
}
}
复制代码
(2) 在模块restTemplate新建controller,通过 restTemplate.getForObject
来调用注册中心中的服务
- restTemplate.getForObject
- 只需要知道服务提供的访问地址即可,不需要知道服务的名称等等
resTemplate/java/com.example.restTemplate/controller/UserController
---
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/service-user")
public User getServiceUser() {
// 通过 restTemplate.getForObject 调用注册中心的服务
// 第一个参数是服务地址
// 第二个参数是数据返回的接收类
return restTemplate.getForObject("http://localhost:8010/user", User.class);
}
}
复制代码
(3) 启动restTemplate,然后即可访问/service-use来访问到注册中心的服务
(五) 服务消费者 consumer
- 创建新的子module/eurekaConsumer
- 在子module/eurekaConsumer/pom.xml引入clound-client依赖
- 在子module/eurekaConsumer/resouces/application.yml中配置eureka
- 在java/com.example.eurekaConsumer/EurekaConsumerApplication启动类
(1) consumer和普通的普通module调用服务有什么区别?
- 区别是 consumer 在注册中心注册了,而比如上面的restTemplate没有在注册中心注册
- 虽然都可以调用注册中心注册的服务,但是restTemplate本身并没有在注册中心注册过
(2) 具体步骤如下
1. eurekaConsumer/pom.xml
---
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
复制代码
2. eurekaConsumer/resouces/application.yml
---
server:
port: 8030
spring:
application:
name: consumer
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
复制代码
3. 在子module/eurekaConsumer/java/com.example.eurekaConsumer/EurekaConsumerApplication
---
@SpringBootApplication
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
复制代码
(六) 服务网关 zuul
- Zuul 是Netfix提供的开源的 ( API网关服务器 ),是客户端和服务端所有请求的 ( 中间层 ),对外开发一个API,将所有请求导入统一的入口,屏蔽了服务端的具体实现逻辑
- Zuul 可以实现
反向代理
- 在网关内部实现
动态路由
,身份认证
,IP过滤
,数据监控
,等功能 Zuul 自带负载均衡,可以修改服务提供者的代码
(1) 新建module/zuul,然后在pom.xml中添加 ( eureka-client ) 和 ( zuul ) 依赖
zuul/pom.xml
---
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
复制代码
(2) 新建 zuul/src/main/resources/application.yml 并添加zuul规则
server:
port: 8040
spring:
application:
name: gateway
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
provider: /p/** # 给服务提供者 provider 设置映射
复制代码
(3) 创建启动类 ZuulApplication
// @EnableZuulProxy:包含了 @EnableZuulServers 设置该类是网关的启动类
// @EnableAutoConfiguration:可以帮助springBoot将所有符合条件@Configuration配置加载到当前IOC容器中
@EnableZuulProxy
@EnableAutoConfiguration
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
复制代码
(七) Ribbon
- 是负载均衡的一种解决方案,基于 Netflix Ribbon 实现
- 在这册中心对Ribbon进行注册后,
Ribbon就可以基于某种负载均衡算法,自动的帮助服务消费者调用接口
,开发者也可以根据需求自定义Ribbon的负载均衡算法,- 轮询
- 随机
- 加权轮训
- 加权随机
- 在实际开发中Ribbon需要结合eureka来使用,Eureka Server提供所有可以调用的服务列表,Ribbon基于特定的负载均衡算法从这些服务中提供者中选择要调用的实例
(1) 具体过程
- 新建module/ribbon
- 在pom.xml中添加eureka-client依赖
- 新建 application.yml 配置 端口,eureka等
- 新建启动类,RibbonApplidation,注意注解
@LoadBalanced
@LoadBalanced 声明一个基于Ribbon的负载均衡
- balance是均衡,平衡的意思
1. pom.xml
---
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
复制代码
2. application.yml
---
server:
port: 8060
spring:
application:
name: ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
复制代码
3. RibbonApplication
---
package com.example.ribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
@Bean
@LoadBalanced // 声明一个基于Ribbon的负载均衡
RestTemplate restTemplate() {
return new RestTemplate();
}
}
复制代码
4. controller/UserController
---
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/ribbon-user")
public User getServiceUser() {
// 通过 restTemplate.getForObject 调用注册中心的服务
// 第一个参数是服务地址
// 第二个参数是数据返回的接收类
// 注意这里的写法和下面的等价,即可以使用注册中心的服务名代替服务提供的具体地址
return restTemplate.getForObject("http://provider/user", User.class);
// return restTemplate.getForObject("http://localhost:8010/user", User.class);
}
}
复制代码