版本相关
与Springboot对应版本
从中央仓库找对应版本
版本变动
因netflix相关组件不再维护,2020版本移除了netflix相关组件,下面不再维护的建议只在2020版本前使用
版本管理依赖
由版本管理依赖管理SpringCloud组件版本,不需要手动配置
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注册中心
Eureka
配置
用户端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
用户端注解
@EnableEurekaClient
服务端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
服务端注解
@EnableEurekaServer
常用配置文件
server:
port: 9000
Spring:
application:
name: Eureka1
eureka:
client:
fetch-registry: false #是否从注册中心获取注册信息(服务端填false,客户端选填)
register-with-eureka: false # 是否向注册中心注册(服务端填false,客户端选填)
# enabled: true #是否启用客户端
service-url:
defaultZone: http://server1:9000/eureka/ #指定注册中心地址,多个用逗号分割(服务端单例填自己,集群填其他服务端)
registry-fetch-interval-seconds: 30 #多少秒从注册中心拉一次服务列表
server:
# renewal-percent-threshold: 0.85 # 85%客户端无法连接时开启自我保护,不改动服务列表
# enable-self-preservation: false #是否开启自我保护()
instance:
prefer-ip-address: true #是否优先用ip地址作为主机名标识
appname: name # 服务名,未配置则用spring.application.name 都没配就是unknown
# lease-expiration-duration-in-seconds: 90 #指定服务端可接受最长时间无心跳客户端连接
# lease-renewal-interval-in-seconds: 5 #指定客户端发送心跳时间
# hostname: localhost # 主机名称,不配置时用操作系统主机名
声明式调用客户端Feign
Maven配置
Maven 2020版本以前 默认集成了
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2020版本移除了Hystrix和Ribbon,需要使用新依赖支持负载均衡loadbalancer
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
使用
使用实例
http://t.csdn.cn/MBsUL
启动类上加@EnableFeignClients
调用Eureka客户端“服务ID”暴露的“/test”接口,会生成代理Bean,对父接口方法也生效,可用于公共模块
@FeignClient(name = "服务ID")
public interface Service {
@GetMapping("/test")
public String test(@RequestParam("name") String name);
}
Yml配置
feign:
client:
config:
hystrix:
enabled: true #开启Feign的熔断功能 2020版本失效
compression:
request:
enabled:
okhttp:
enabled:
httpclient:
enabled: true
负载均衡
Ribbon(不再维护)
配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
ribbon: # 对所有服务生效
eureka:
enabled: true
NFLoadBalancerRuleClassName: 负载均衡策略类
ConnectTimeout: 5000 #连接超时时间,默认1s(1000)
ReadTimeout: 5000 #读取超时时间
OkToRetryOnAllOperations: true #对所有操作请求都进行重试
MaxAutoRetries: 1 #对当前实例的重试次数
MaxAutoRetriesNextServer: 2 #切换实例的重试次数
serviceID: # 对某个服务生效
ribbon:
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
return restTemplateBuilder.build();
}
使用返回的RestTemplate Bean会负载均衡
使用实例
负载均衡策略使用实例
负载均衡策略配置 http://t.csdn.cn/Cahhq
熔断/降级
Hystrix(不再维护)
在客户端熔断
配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
降级
启动类加@EnableHystrix
API方法上使用
@Service
public class LocalItemService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hi(String id) {
return restTemplate.getForObject("http://hystrix-provider/hi?id=" + id, String.class);
}
public String hiError(String id) {
return String.format("Hi,your message is : %s but request bad.", id);
}
}
服务端不可用时会触发fallbackMethod方法
客户端降级
feign:
hystrix:
enabled: true #开启Feign的熔断功能 2020版本失效
Feign调用
@FeignClient(value = "hystrix-provider", configuration = HystrixConfig.class, fallback = LocalItemServiceImpl.class)
public interface LocalItemService{
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String hi(@RequestParam(value = "id")String id);
}
@Configuration
public class HystrixConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
熔断触发调用类
@Component
public class LocalItemServiceImpl implements LocalItemService{
@Override
public String hi(String id) {
return String.format("Hi,your message is : %s but request bad.",id);
}
}
网关
Zuul(不再维护)
默认支持ribbon和hystrix,建议在2020版本前使用
配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
zuul:
routes:
consumer-prod:
path: /consumer-prod/** # * 匹配任意数量字符 , ? 匹配任意单个字符 、 ** 匹配任意数量目录
serviceId: consumer-prod # 将所有/consumer-prod 请求转到consumer-prod
service2:
path: /service2/** #默认为service2与所有服务创建映射
host:
connect-timeout-millis: 200000
socket-timeout-millis: 200000
ignored-services: '*' #忽略服务,可被上面覆盖,可用于关闭默认映射规则
prefix: "/pre" # 前缀
strip-prefix: true #否在转发前从路径中删除前缀
熔断
默认集成Hystrix
@Component
public class MyFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
return "eureka-consumer";//对eureka-consumer服务开启熔断,返回*则对所有服务开启
}
@Override
public ClientHttpResponse fallbackResponse(String route,
Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return this.getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("连接异常,I'm the fallback".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application", "json",
Charset.forName("UTF-8"));
headers.setContentType(mt);
return headers;
}
};
}
}
过滤器
zuul定义了四种过滤器
- pre 请求被路由之前调用
- route 负责把请求转发到服务
- error 请求发送错误时调用
- post 在route和error过滤器之后调用
@Component
public class PreRequestLogFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(
PreRequestLogFilter.class);
@Override
public String filterType(){
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter(){
return true;
}
@Override
public Object run(){
//获取当前请求上下文
RequestContext ctx = RequestContext.getCurrentContext();
//取出当前请求
HttpServletRequest request = ctx.getRequest();
logger.info("进入访问过滤器,访问的url:{},访问的方法:{}",request.getRequestURL(),request.getMethod());
//从headers中取出key为accessToken值
String accessToken = request.getHeader("accessToken");//这里我把token写进headers中了
//这里简单校验下如果headers中没有这个accessToken或者该值为空的情况
//那么就拦截不入放行,返回401状态码
if(StringUtils.isEmpty(accessToken)) {
logger.info("当前请求没有accessToken");
//使用Zuul来过滤这次请求
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
logger.info("请求通过过滤器");
return null;
}
}
Gateway
配置
相关资料
http://t.csdn.cn/4bDL4
使用Gateway时不能同时使用spring-boot-starter-web<依赖
<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-gateway</artifactId>
</dependency>
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 默认为false,设置为true表明spring cloud gateway开启服务发现和路由的功能,网关自动根据注册中心的服务名为每个服务创建一个router,将以服务名开头的请求路径转发到对应的服务
lower-case-service-id: true #启动 locator.enabled=true 自动路由时,路由的路径默认会使用大写ID,若想要使用小写ID,可将lowerCaseServiceId设置为true
routes: #路由
# 路由id,可以随意写,唯一即可
- id: user-service-route
# 代理的服务地址;lb表示通过负载均衡从eureka中通过服务id获取具体服务
uri: lb://consumer-user
# 路由断言,可以配置映射路径
predicates: #断言
- Path=/consumer-user
filters: #当前路由下的局部过滤器
# 添加请求路径的前缀
# - PrefixPath=/user
default-filters: #全局过滤器
# -
自定义过滤器/异常处理
Gateway有预设过滤器,也可以自定义过滤器
自定义过滤器看这篇博客Spring Cloud Gateway 服务网关的部署与使用详细介绍_gateway网关_张维鹏的博客,没了看上面相关资料
配置中心
SpringCloudConfig
配置实例
实例
http://t.csdn.cn/zQcTJ
服务端配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
启动类加@EnableConfigServer
读取配置方式
- 从本地读取
spring:
cloud:
config:
server:
native:
search-locations: classpath:/shared/ # 配置文件所在目录 配置文件名称格式为 服务ID-profile.yml 例如consumer-user-dev.yml
- 从远程Git仓库读取
spring:
cloud:
config:
server:
git:
username: username #用户名
password: password #密码
uri: 远程仓库地址 #要读取的远程仓库的配置文件的地址
search-paths: cong #远程仓库文件夹地址
default-label: master # 指定分支,不指定则默认master
用户端配置
<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-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
配置文件要写在bootstrap.yml文件中
spring:
cloud:
config:
discovery:
service-id: 注册中心服务ID #注册中心服务ID
enabled: true #开启客户端
# label: master # 指定分支,不指定则使用默认分支
name: service1 # 指定应用名称,(默认服务id?没试过) 寻找name-profile.yml文件 本例中寻找 service1-dev.yml
profile: dev # 指定激活环境,默认default 寻找name-profile.yml文件 本例中寻找 service1-dev.yml
动态刷新
实例
http://t.csdn.cn/Qelxr
所有服务实例加
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.4.3</version>
</dependency>
配置中心和(配置中心存储的客户端配置文件或客户端配置文件)配置rabbitmq地址
spring:
rabbitmq:
host: 主机地址
port:
username:
password:
如果RabbitMQ配置在配置中心,客户端配置
spring:
cloud:
config:
fail-fast: true #允许拉取配置文件前无法连接RabbitMQ
需要动态刷新的类上加@RefreshScope