springboot和springcloud之间的关系?
springboot是spring的一套快速配置脚手架,可以基于springboot快速开发单个微服务,springcloud是一个基于springboot实现的开发工具;springboot专注于快速、方便集成单个微服务个体,spring cloud关注全局的服务治理框架,其很大一部分事基于springboot来实现,必须基于springboot开发,可以单独使用springboot开发项目,但是springcloud离不开springboot。
服务发现—Nacos
实现不同的微服务模块之间的调用,把这些模块在注册中心进行注册,注册之后,实现互相调用
Nacos是以服务为主要服务对象的中间件,Nacos支持所有主流的服务发现、配置和管理。
Nacos主要提供以下四大功能:
- 服务发现和服务健康监测
- 动态配置服务
- 动态DNS服务
- 服务及其元数据管理
nacos下载和安装:
(1)下载地址和版本
nacos下载地址
启动nacos服务
-
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式)
启动命令:sh startup.sh -m standalone -
Windows
启动命令:cmd startup.cmd 或者双击startup.cmd运行文件。
访问:http://localhost:8848/nacos
用户名密码:nacos/nacos
服务注册流程
微服务调用方和提供方都需要在nacos注册中心中完成注册!
1:被注册服务需引入Nacos的pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2:在被注册服务的application.properties中添加Nacos服务的配置信息
nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3:在被注册服务的启动类上添加注解@EnableDiscoveryClient
服务调用—Feign
Feign可以帮助我们更快捷、优雅地调用HTTP API;
使用前提:一个服务需要调用另外一个服务中的接口方法
即 调用方(消费者)—被调用方(生产者)
服务调用流程:@PathVariable注解一定要指定参数名称,否则出错
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在调用方的启动类上添加注解@EnableFeignClients
3、创建包和接口
3.1、创建client包
3.2、创建接口
@FeignClient("service-vod") //指定被调用方所在服务名
@Component
public interface VodClient {
//直接复制被调用接口即可
@DeleteMapping(value = "/eduvod/vod/video/{videoId}") //完全路径
public R removeVideo(@PathVariable("videoId") String videoId); //只要方法名
}
熔断器——Hystrix
熔断器基本概念:
Hystrix 是一个供分布式系统使用,提供延迟和容错功能,保证复杂的分布系统在面临不可避免的失败时,仍能有其弹性。
比如系统中有很多服务,当某些服务不稳定的时候,使用这些服务的用户线程将会阻塞,如果没有隔离机制,系统随时就有可能会挂掉,从而带来很大的风险。SpringCloud使用Hystrix组件提供断路器、资源隔离与自我修复功能。下图表示服务B触发了断路器,阻止了级联失败。
也就是说,当某一服务方所在机器出现宕机、请求超时等阻塞情况时,熔断器会切断远程调用,防止多个服务发生级联灾害。
springcloud在接口调用上回经过几个组件配合:
Feign ----->Hystrix —>Ribbon —>Http Client(apache http components 或者 Okhttp)
熔断器的使用:
熔断器是在消费者(调用端)使用;配合Feign使用
1、添加依赖
<!-- ribbon负载均衡器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!--hystrix熔断器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、添加hystrix配置(在配置文件中开启熔断器)
#开启熔断机制
feign.hystrix.enabled=true
#设置hystrix超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
3、创建interface接口及接口实现类,在实现类中编写出错内容
package com.zhmsky.eduService.client;
import com.zhmsky.result.Result;
import com.zhmsky.result.ResultUtil;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author zhmsky
* @date 2022/6/19 17:23
*/
@Component
public class HystrixFeignClientImpl implements VodClient{
//在出错时执行
@Override
public Result<String> deleteVideoForAliYun(String videoId) {
return new ResultUtil<String>().setErrorMsg("删除视频出错了!");
}
@Override
public Result<String> deleteBatchVideo(List<String> videoIdList) {
return new ResultUtil<String>().setErrorMsg("删除视频出错了!");
}
}
4、消费者服务启动类注解
@FeignClient(name = "service-vod",fallback = HystrixFeignClientImpl.class) //调用的服务名
其本质上就是如果远程接口调用成功,那么执行对应接口中的方法;如果调用失败,则通过fallback执行实现类中的方法(出错时执行的方法)
网关——Spring Cloud Gateway
API网关简介
API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
(1)客户端会多次请求不同的微服务,增加了客户端的复杂性。
(2)存在跨域请求,在一定场景下处理相对复杂。
(3)认证复杂,每个服务都需要独立认证。
(4)难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
(5)某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。
以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性。
将Gateway网关和各种微服务均在Nacos中心完成注册,然后通过Gateway网关访问其它其它服务。
Gateway网关作用流程:
Spring cloud Gateway发出请求。然后再由Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器将请求发送到我们实际的服务执行业务逻辑,然后返回。
实现方式
将各微服务、Gateway网关在nacos注册中心完成注册。 在Gateway网关服务中配置规则。
Gateway网关服务:
#服务端口
server.port=8008
#服务名
spring.application.name=service-gateway
#nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#使用服务发现路由(通过网关找到服务)
spring.cloud.gateway.discovery.locator.enabled=true
#服务路由名小写
#spring.cloud.gateway.discovery.locator.lower-case-service-id=true
#配置service-edu服务
#服务名
spring.cloud.gateway.routes[0].id=service-edu
#被注册的服务名
spring.cloud.gateway.routes[0].uri=lb://service-edu
#路由匹配规则
spring.cloud.gateway.routes[0].predicates= Path=/eduService/**
#配置service-ucenter服务
#服务名
spring.cloud.gateway.routes[1].id=service-ucenter
#被注册的服务名
spring.cloud.gateway.routes[1].uri=lb://service-ucenter
#路由匹配规则
spring.cloud.gateway.routes[1].predicates= Path=/serviceUcenter/**
edu服务:
edu服务配置文件
server.port=8001
spring.application.name=service-edu
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
eduController
/**
* <p>
* 讲师 前端控制器
* </p>
*
* @author zhmsky
* @since 2022-03-20
*/
@RestController
@RequestMapping("/eduService/teacher")
@CrossOrigin
@Api("讲师管理")
public class EduTeacherController {
@Autowired
private EduTeacherService teacherService;
//查询所有讲师信息
@GetMapping("/getAll")
@ApiOperation("查询所有讲师信息")
public Result<List<EduTeacher>> getAll() {
List<EduTeacher> list = teacherService.list();
return new ResultUtil<List<EduTeacher>>().setData(list);
}
}
启动各个微服务模块,首先直接访问edu服务的getAll请求,http://localhost:8001/eduService/teacher/getAll
接着因为edu服务在nacos中完成了注册,所以gateway网关通过路由匹配可以找到对应的edu服务,从而实现通过Gateway网关访问到edu服务中的请求,
http://localhost:8008/eduService/teacher/getAll