SpringCloud(二) - Eureka注册中心,feign远程调用,hystrix降级和熔断
1、项目模块介绍
2、 父项目
主要依赖 spring-cloud 的 版本控制
<properties>
<!-- springCloud 版本 -->
<scd.version>Dalston.SR4</scd.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${scd.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3、 eureka 模块
3.1 主要依赖
<!-- eureka 注册中心 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
3.2 配置信息
# 端口
server:
port: 8096
# 服务名
spring:
application:
name: edocmall-eureka
# eureka 服务注册与发现 配置
eureka:
client:
#Eureka 监控页面
service-url:
defaultZone: http://127.0.0.1:${server.port}/eureka
register-with-eureka: false # 是否注册自己的服务到注册中心,默认为true
on-demand-update-status-change: false # 是否主动拉取其他注册的服务信息,默认也是true
3.3 主启动类上的注解
@EnableEurekaServer //eureka服务端启动,可以就接受别人来注册
3.4 测试 访问
启动项目,访问 http://localhost:8096
4、server 服务提供模块
4.1 主要依赖
<!-- eureka 客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
4.2 配置信息
# 端口
server:
port: 8097
# 服务名配置,eureka注册信息,服务调用基于服务名,必须增加
spring:
application:
name: edocmall-server
#数据源配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/kh96_springboot_edocbd?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
# mybatis-plus 配置
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
# eureka 注册中心的配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8096/eureka # 注册中心的地址
# 关闭自我保护机制,保证不可用的服务及时剔除
server:
enable-self-preservation: false
4.3 代码介绍
4.4 主启动类上的注解
@MapperScan("com.kgc.scd.mapper")
@EnableEurekaClient // 开启 eureka 服务注册,将此服务注册到 eureka中
4.5 请求测试
服务提供端的请求最好先单独测试一下,成功后再进行远程调用;
5、 web 服务消费模块
5.1 使用restTemplate 调用
5.1.1 主启动类 向容器中放入 restTemplate
@SpringBootApplication
public class Edocmall96WebApplication {
public static void main(String[] args) {
SpringApplication.run(Edocmall96WebApplication.class, args);
}
//往容器中添加 restTemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
5.1.2 请求中直接调用具体url下的请求
@RestController
public class WebEntryController {
@Autowired
private RestTemplate restTemplate;
// 根据文档编号,获取文档详情
@GetMapping("/entryById")
public RequestResult<EdocEntryVO> entryDetail(Integer id){
log.info("------ 根据文档编号:{},获取文档详情 ------",id);
//模拟发送http请求请求server端,获取文档详情
//弊端:消费端,必须在程序内,记录提供者的ip地址,如果地址出现变更,还需要计时更新,如果服务者有多个及其,无法实现负载均衡
EdocEntryVO edocEntryVO = restTemplate.getForObject("http://127.0.0.1:8097/entry?id="+id,EdocEntryVO.class);
return ResultBuildUtil.success(edocEntryVO);
}
}
5.1.3 请求测试
5.2 使用 feign 远程调用
5.2.1 主要依赖
<!-- eureka 客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- feign远程调用依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
5.2.2 配置信息
# 端口
server:
port: 8098
spring:
application:
name: edocmall-web
# 服务名
# eureka 注册中心的配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8096/eureka
# 关闭自我保护机制,保证不可用的服务及时剔除
server:
enable-self-preservation: false
# 开启客户端服务降级,默认是关闭的,需要打开
feign:
hystrix:
enabled: true
5.2.3 代码介绍
5.2.3.1 业务层接口
//指定服务名
@FeignClient(value = "edocmall-server")
public interface WebEntryService {
//基于feign 远程调用edoc-server服务端提供的查询文档详情接口
@GetMapping("/entry") //必须跟远程请求一直
EdocEntryVO invokeEntryServiceUserFeign(@RequestParam("id") Integer id); //必须写 @RequestParam("id")
// 注意 一点更要写 @RequestParam("id") 里面的参数必须写
}
5.2.3.1 控制层直接调用接口
@RestController
public class WebEntryController {
@Autowired
private WebEntryService webEntryService;
// 根据文档编号,获取文档详情
@GetMapping("/entryById")
public RequestResult<EdocEntryVO> entryDetail(Integer id){
log.info("------ 根据文档编号:{},获取文档详情 ------",id);
//基于feign 远程调用服务端接口,获取文档详情
EdocEntryVO edocEntryVO = webEntryService.invokeEntryServiceUserFeign(id);
return ResultBuildUtil.success(edocEntryVO);
}
}
5.2.4 主启动类上的注解
@EnableEurekaClient // 开启 eureka 服务注册,将此服务注册到 eureka中
@EnableFeignClients //开启 feign 远程调用服务
5.2.5 请求测试
eureka 注册中心:
feign远程调用:
6、Feign的服务降级与熔断
6.1 服务降级(服务消费端)
6.1.1 依赖
由于feign中有hystrix的依赖,所以不用单独添加;
6.1.2 hytrix 配置
# 开启客户端服务降级,默认是关闭的,需要打开
feign:
hystrix:
enabled: true
6.1.3 接口指定服务降级后的实现类
@FeignClient(value = "edocmall-server",fallback = WebEntryServiceImpl.class) //fallback 指定调用失败后 降级调用的数据
public interface WebEntryService {
......
}
6.1.4 实现类,具体降级服务操作
@Service
public class WebEntryServiceImpl implements WebEntryService {
@Override
public EdocEntryVO invokeEntryServiceUserFeign(Integer id) {
//此方法,就是regn远程调用,触发服务剪辑的默认实现,正常请求不会调用
//只用远程 feign调用失败,才会调用
EdocEntryVO edocEntryVO = new EdocEntryVO();
edocEntryVO.setId(999);
edocEntryVO.setCid(0);
edocEntryVO.setTitle("触发熔断服务降级");
edocEntryVO.setSummary("当feign远程调用接口失败,默的默认实现");
edocEntryVO.setUploadUser("feign-hystrix");
edocEntryVO.setCreateDate(new Date());
return edocEntryVO;
}
6.1.5 测试
6.1.5.1 不添加服务降级时 服务端宕机情况
6.1.5.2 添加服务降级后 服务端宕机情况
6.1.5.3 添加服务降级后 服务端正常,接口报错
接口报错信息:
6.2 服务熔断(服务提供端)
6.2.1 依赖
<!--导入Hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
6.2.2 熔断 备选方法 和 熔断触发条件
@Slf4j
@RestController
public class EntryController {
@Autowired
private EntryService entryService;
//根据 id 查询文档详情
@GetMapping("/entry")
@HystrixCommand(fallbackMethod = "fallbackStoryDetail") //指定 服务熔断后的备选方法
public EdocEntryVO entryDetail(@RequestParam Integer id){
log.info("------ 根据文档编号:{},获取文档详情 ------",id);
EdocEntryVO edocEntry = entryService.getEdocEntryById(id);
if (edocEntry == null){
//抛出异常,触发 熔断 备选方法
throw new RuntimeException("id为:"+id+"的用户不存在,触发服务熔断");
}
return edocEntry;
}
// 根据 id 查询文档详情 方法 服务熔断后 的备选方案
public EdocEntryVO fallbackStoryDetail(@RequestParam Integer id){
//此方法,只用服务熔断时,才会被调用
EdocEntryVO edocEntryVO = new EdocEntryVO();
edocEntryVO.setId(999);
edocEntryVO.setCid(0);
edocEntryVO.setTitle("根据 id 查询文档详情 方法 服务熔断后 的备选方案");
edocEntryVO.setSummary("当根据id 查询不到具体用户信息时,就会触发");
edocEntryVO.setUploadUser("hystrix");
edocEntryVO.setCreateDate(new Date());
return edocEntryVO;
}
}
6.2.3 主启动类上的注解
@EnableHystrix //开启熔断服务 旧的开启服务熔断注解: @EnableCircuitBreaker
6.2.4 测试
6.2.4.1 没有服务降级,也没有服务熔断 时
直接返回错误;
6.2.4.2 有服务降级,没有服务熔断 时
触发服务降级;
6.2.4.3 有服务降级,也有服务熔断 时
触发服务熔断;
7、显示eureka中服务的基本信息
7.1 依赖
<!-- 暴露info端点给外部访问, 需要添加暴露端点的启动依赖: -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
7.2 配置
# 服务信息 eureka 中服务配置的基本信息
info:
app.name: web 消费端
company.name: com.kgc.kh96 # 公司域名
# 其他信息可以自行查询
7.3 测试
点击服务路径:
点击后的测试信息:
8、eureka注册中心进行加密
8.1Eureka加密的重要性
如果我们不对Eureka进行加密就会导致一些恶意的微服务注册到Eureka注册中心,为了防止这种事情发生我们就要对Eureka进行加密处理。
8.2 实现步骤
8.2.1 配置依赖 maven
Eureka 自带了一个 Web 的管理页面,方便我们查询注册到上面的实例信息,但是有一个问题:如果在实际使用中,注册中心地址有公网 IP 的话,必然能直接访问到,这样是不安全的。所以我们需要对 Eureka 进行改造,加上权限认证来保证安全性。
改造我们的 eureka-server,通过集成 Spring-Security 来进行安全认证。
在 pom.xml 中添加 Spring-Security 的依赖包,代码如下所示。
<!-- eureka依赖配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- Spring-Security 的依赖包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
8.2.2 springboot Eureka注册中心 配置文件
8.2.2.1yml文件:
spring:
security:
user:
name: Your username
password: Yourpassword
8.2.2.1properties格式:
spring.security.user.name: Your username
spring.security.user.name: Your password
8.2.3 注册中心security配置
package com.dazuizui.eureka1.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/* @Override
protected void configure(HttpSecurity http) throws Exception {
// 关闭csrf
http.csrf().disable();
// 支持httpBasic
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//过滤eureka路径
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
8.2.3 注册中心的配置文件
8.2.3.1 yml版:
#服务名
spring:
application:
name: eureka
basic:
enable: true
# security在springboot 2.0.0版本后需要在spring的层级下才能成功,2.0.0之前的版本不需要在spring的层级下
security:
user:
name: admin
password: admin
# 端口号
server:
port: 8096
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/
fetch-registry: true # 是否主动拉取其它注册的服务信息,默认也是true
register-with-eureka: false # 是否注册自己的服务到注册中心,默认是true
重新启动注册中心,访问 http://localhost:8096/,此时浏览器会提示你输入用户名和密码,输入正确后才能继续访问 Eureka 提供的管理页面。
8.2.4 eureka服务端注册的配置文件配置
在 Eureka 开启认证后,客户端注册的配置也要加上认证的用户名和密码信息,需要对应的账户和密码:
# 端口
server:
port: 8100
# 服务名
spring:
application:
name: wyyxmall-hx-server
# eureka注册中心配置
eureka:
client:
service-url:
defaultZone: http://admin:admin@localhost:8096/eureka/
8.2.5 若出现配置eureka认证后输入密码还报错无法进入的情况
8.2.5.1 在进行eureka server安全认证时,登陆用户名密码报错。
8.2.5.2 方法一:springboot 2.0.0版本之前
springboot 2.0.0版本之前的 配置文件application.yml配置如下:
# security在springboot 2.0.0版本后需要在spring的层级下才能成功,2.0.0之前的版本不需要在spring的层级下
security:
basic:
enable: true
user:
name: admin
password: admin
8.2.5.3 方法二:springboot 2.0.0版本之后
springboot 2.0.0版本之后的 配置文件application.yml配置如下:
spring:
security:
basic:
enable: true
user:
name: admin
password: admin