eureka(注册中心)组件
#先添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
#配置application.yml
eureka:
client:
# 表示是否将自己注册到Eureka Server,默认为true。
register-with-eureka: false
# 表示是否从Eureka Server获取注册信息,默认为true。
fetch-registry: false
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8000/eureka ;多个地址可使用,分隔
service-url:
defaultZone: http://localhost:8000/eureka/
server:
eviction-interval-timer-in-ms: 1000 # 续期时间,即扫描失效服务的间隔时间(单位毫秒,默认是60*1000)测试时关闭自我保护机制,保证不可用服务及时踢出
enableSelfPreservation: false # 设为false,关闭自我保护
#启动类上加注解
@EableEurekaServer
ribbon(负载均衡)组件
#ribbon依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
#配置ribbon的application.yml文件
ribbon:
MaxAutoRetries: 2 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试
MaxAutoRetriesNextServer: 3 #切换实例的重试次数
OkToRetryOnAllOperations: false #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
ConnectTimeout: 5000 #请求连接的超时时间
ReadTimeout: 6000 #请求处理的超时时间
feign(负载均衡,远程调用)组件
#feign组件的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
#定义FeignClient接口
在client2中创建client包,定义查询client1的客户端该用接口,
@FeignClient(value = "TEST-PRODUCER1")//调用的唯一标识
public interface ClientInterface {
//远程调用client服务中的test01接口
@GetMapping("/test/getString")//标识远程调用的http的方法类型是什么
public String test01();
}
#启动类上加@EnableFeignClients注解
Feign工作原理如下:
1、 启动类添加@EnableFeignClients注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理对象
2、@FeignClient(value = "TEST-CLIENT1")即指定了cms的服务名称,Feign会从注册中心获取cms服务列表,并通过负载均衡算法进行服务调用。
3、在接口方法 中使用注解 @GetMapping("/test/getString"),指定调用的url,Feign将根据url进行远程调用。
Feign注意点
SpringCloud对Feign进行了增强兼容了SpringMVC的注解 ,我们在使用SpringMVC的注解时需要注意:
1、feignClient接口 有参数在参数必须加@PathVariable("XXX")和@RequestParam("XXX")
2、feignClient返回值为复杂对象时其类型必须有无参构造函数。
zuul(服务网关)组件
#zuul组件和eureka-client使用的方式
#添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-client</artifactId>
</dependency>
#配置application.yml文件
#注册到eureka 服务端
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
zuul:
#转发是带头部信息,携带cookie信息
sensitive-headers:
#启动类上加@EnableZuulProxy注解,支持网关路由
zuul过滤器
创建一个类继承ZuulFilter抽象类
@Component //交给Ioc处理
public class TestZuulFilter extends ZuulFilter {
}
指定当前过滤器的类型(继承ZuulFilter父类的方法)
@Override
/*PRE:在请求被路由之前调用,可以使用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试Log等。
*ROUTE:将请求路由到对应的微服务,用于构建发送给微服务的请求。
*POST:在请求被路由到对应的微服务以后执行,可用来为Response添加HTTP Header、将微服务的Response发送给客户端*等。
*ERROR:在其他阶段发生错误时执行该过滤器。
*/
public String filterType() {
return FilterConstants.PRE_TYPE;
}
指定过滤器的执行顺序
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
配置是否启用
@Override
public boolean shouldFilter() {
// 开启当前过滤器
return true;
}
指定过滤器中的具体业务
@Override
public Object run() throws ZuulException {
@Override
public Object run() throws ZuulException {
//1. 获取Request对象
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//2. 获取token参数
String token = request.getParameter("token");
//3. 对比token
if(token == null || !"123".equalsIgnoreCase(token)) {
//4. token校验失败,直接响应数据
baseResp.setMessage("验证失败");
currentContext.getResponse().setContentType("text/html;charset=UTF-8");
currentContext.setResponseBody(baseResp.toString());
//停止继续执行。
currentContext.setSendZuulResponse(false)
}
return null;
}
zuul的降级
创建一个类实现FallbackProvider
@Component //交给Ioc处理
public class ZuulFallBack implements FallbackProvider {}
重写两个方法
@Override
public String getRoute() {
return "*"; // 代表指定全部出现问题的服务,都走这个降级方法
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
System.out.println("降级的服务:" + route);
cause.printStackTrace();
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
// 指定具体的HttpStatus
return HttpStatus.INTERNAL_SERVER_ERROR;
}
@Override
public int getRawStatusCode() throws IOException {
// 返回的状态码
return HttpStatus.INTERNAL_SERVER_ERROR.value();
}
@Override
public String getStatusText() throws IOException {
// 指定错误信息
return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
// 给用户响应的信息
String msg = "当前服务:" + route + "出现问题!!!";
return new ByteArrayInputStream(msg.getBytes());
}
@Override
public HttpHeaders getHeaders() {
// 指定响应头信息
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
config组件
本地配置
#添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
#配置appication.yml文件
spring:
application:
name: spring-cloud-config-server
profiles:
active: native # 配置使用本地储存
cloud:
config:
server:
native:
search-locations: classpath:properties/ # 搜索src/main/resource 下的properties文件夹下的文件
#在resource下创建文件prpoperties文件下创建
neo-config-dev.properties //开发环境
neo-config-pro.properties //产品环境
neo-config-test.properties //测试环境
#启动类上加@EenableConfigServer,激活对配置中心的支持
#测试http://localhost:8006/neo-config/dev
客户端配置
#客户端上加的依赖包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
#将application.yml改为bootstrap.yml文件
##config-客户端的配置文件`
spring:
application:
name: zuul-eureka
cloud:
config:
discovery:
enabled: true
service-id: config-server
name: shop-config
profile: dev
spring.application.name:对应{application}部分
spring.cloud.config.profile:对应{profile}部分
spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用
spring.cloud.config.uri:配置中心的具体地址
spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。
特别注意:上面这些与spring-cloud相关的属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties。
git环境配置
#在config-server端添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
#服务端的配置文件
server:
port: 8006
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/miaohangbo/config-repo.git/ # 配置git仓库的地址
search-paths: config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
#可以不用写
username: miaohangbo # git仓库的账号
password: aini59852369 # git仓库的密码
refresh刷新
#在客户端添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
#开启更新机制
需要给加载变量的类上面加载`@RefreshScope`,在客户端执行`/refresh`的时候就会更新此类下面的变量值。
#在客户端配置文件加入
management.endpoints.web.exposure.include=refresh
#`http://localhost:8003/actuator/refresh`
Hystyix服务熔断、降级
使用Hystyix
<!-- Hystrix 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
#在启动类上加@EnableCircuitBreaker注解
修改Colltroller
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/getString")
//- Hystrix的线程池(默认),接收用户请求采用tomcat的线程池,执行业务代码,调用其他服务时,采用Hystrix的线程池。
- 信号量,使用的还是Tomcat的线程池,帮助我们去管理Tomcat的线程池
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy",value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")},
fallbackMethod = "getMsgFallback")
@ResponseBody
public String test01(){
int i =1/0;
return "你好,调用成功";
}
public String getMsgFallback() {
return "祝您 2021 牛年大吉";
}
}
Feigin结合Hystrix
#在调用方导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
#消费启动类开启@EnableHytrix
#消费者配置文件
#feign结合hystrix使用
feign:
hystrix:
enabled: true
hystrix:
command:
default: #default全局有效,service id指定应用有效
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 20000
通过配置@FeignClient注解的fallback属性来位MessageServiceClient指定一个自定义的fallback处理类(MessageServiceFallback)。
@FeignClient(value = "TEST-CLIENT1",fallback = MessageServiceFallback.class)
public interface ClientInterface {
//远程调用client服务中的test01接口
@GetMapping("/test/getString")//标识远程调用的http的方法类型是什么
public String test01();
}
创建Fallback处理类
MessageServiceFallback需要实现ClientInterface接口,并且在Spring容器中必须存在一个该类型的有效Bean。在这里,我们使用@Component注解将其注入到Spring容器中
@Component
public class MessageServiceFallback implements ClientInterface {
@Override
public String test01() {
System.out.println("调用消息接口失败,对其进行降级处理!");
return "消息接口繁忙,请稍后重试!";
}
}