Spring cloud入门

spring cloud生态

spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、事件总线等等
s

服务的注册与发现(Eureka)

pom引入包

<!--eureka server -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

启动一个服务注册中心,注解@EnableEurekaServer

@EnableEurekaServer
@SpringBootApplication
public class EurekaserverApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaserverApplication.class, args);
    }
}

配置文件application.yml

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

Eureka Ha

配置文件peer1:

spring:
  application:
    name: eureka-ha
server:
  port: 8761
eureka:
  instance:
    hostname: peer1
  client:
    serviceUrl:
      defaultZone: http://peer2:8762/eureka/

配置文件peer2:

spring:
  application:
    name: eureka-ha
server:
  port: 8762
eureka:
  instance:
    hostname: peer2
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/

启动用不同配置文件就完成集群

其他

## 失效剔除
60s检测一次,超过90s没心跳

## 自我保护
## 触发:心跳失败比例 15分钟内<85%
eureka.server.enable-self-preservation=false


## 配置元数据
eureka.instance.metadataMap.zone=shanghai
eureka.instance.key=value

## 随机数
${random.int}
server.port=${random.int[1000,1999]}

## 自定义url
management.context-path=/hello
eureka.instance.statusPageUrlPath=${management.context-path}/info
eureka.instance.healthCheckUrlPath=${management.context-path}/health

## 健康检查交给/health
引入spring-boot-starter-actuator
eureka.client.healthcheck.enabled=true

## 其他配置
preferIpAddress
nonSecurePort
securePort
noneSecurePortEnabled
securePortEnabled
appname
hostname

创建服务提供者 (Eureka client)

引入包

 <dependency>                                    
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka</artifactId>
 </dependency>

controller

@RestController
public class UserController {
    @Autowired
    private UserDao userDao;
    @GetMapping("/user/{id}")
    public User get(@PathVariable Long id) {
        return userDao.findOne(id);
    }
}

配置文件application.yml

server:
  port: 7900
spring:
  application:
    name: provider
eureka:
  client:
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://localhost:8761/eureka/

注解为服务发现(服务提供者)、Eureka客户端

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

其他

## 是否注册eureka
eureka.client.register-with-eureka=true

## 获取服务间隔
eureka.client.register-fetch-interval-seconds=30

## 设置region
eureka.client.region

## 配置元数据
eureka.instance.metadataMap.zone=shanghai
eureka.instance.key=value

## DiscoveryClient类
这个类用于帮助与Eureka Server互相协作。
Eureka Client负责了下面的任务:
- 向Eureka Server注册服务实例
- 向Eureka Server为租约续期
- 当服务关闭期间,向Eureka Server取消租约
- 查询Eureka Server中的服务实例列表

创建服务消费者(ribbon)

引入包

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

application.yml

server:
  port: 8900
spring:
  application:
    name: ribbon
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

通过@EnableDiscoveryClient向服务中心注册
注册了一个bean: restTemplate
通过@ LoadBalanced注册表明,这个restRemplate是负载均衡的

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceRibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

LoadBalancerClient

public interface LoadBalancerClient {
    ServiceInstance choose(String serviceId);
    <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
    URI reconstructURI(ServiceInstance instance, URI original);
}

ServiceInstance choose(String serviceId)
根据传入的服务名serviceId,从负载均衡器中挑选一个对应服务的实例。

T execute(String serviceId, LoadBalancerRequest request) throws IOException
使用从负载均衡器中挑选出的服务实例来执行请求内容。

URI reconstructURI(ServiceInstance instance, URI original)
为系统构建一个合适的“host:port”形式的URI。
在分布式系统中,我们使用逻辑上的服务名称作为host来构建URI
(替代服务实例的“host:port”形式)进行请求,
比如:http://myservice/path/to/service
在该操作的定义中,
前者ServiceInstance对象是带有host和port的具体服务实例,
而后者URI对象则是使用逻辑服务名定义为host的URI,
而返回的URI内容则是通过ServiceInstance的服务实例详情拼接出的具体“host:post”形式的请求地址。

ILoadBalancer

public interface ILoadBalancer {
    public void addServers(List<Server> newServers);
    public Server chooseServer(Object key);
    public void markServerDown(Server server);
    public List<Server> getReachableServers();
    public List<Server> getAllServers();
}

addServers
向负载均衡器中维护的实例列表增加服务实例。

chooseServer
通过某种策略,从负载均衡器中挑选出一个具体的服务实例。

markServerDown
用来通知和标识负载均衡器中某个具体实例已经停止服务,不然负载均衡器在下一次获取服务实例清单前都会认为服务实例均是正常服务的。

getReachableServers
获取当前正常服务的实例列表。

getAllServers
获取所有已知的服务实例列表,包括正常服务和停止服务的实例。

默认实现

IClientConfig -> DefaultClientConfigImpl
IRule -> ZoneAvoidanceRule
ILoadBalancer -> ZoneAwareLoadBalancer
IPing -> NIWSDicoveryPing
ServerList -> DomainExtractingServerList
ServerList<Server> -> ZonePreferenceServerListFilter

重试配置

spring.cloud.loadbalance.retry.enabled=true
xxx.ribbon.ConnectTimeout=250 ##连接超时
xxx.ribbon.ReadTimeout=1000 ## 读超时
xxx.ribbon.OkToRetryOnAllOperations=true ##所有请求进行重试
xxx.ribbon.MaxAutoRetriesNextServer=2 ##切换实例重试次数
xxx.ribbon.MaxAutoRetries=1  ##当前实例重试次数
注意:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000 ##ribbon超时必须大于hystrix 要不然不触发

断路器(Hystrix)

引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

Application增加注解@EnableCircuitBreaker

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class RibbonApplication {
.....

加上@HystrixCommand,并指定fallbackMethod方法。

   @GetMapping("/get/{id}")
    @HystrixCommand(fallbackMethod = "getFailback")
    public User get(@PathVariable Long id) {
        return restTemplate.getForObject("http://PROVIDER/user/" + id, User.class);
    }

    public User getFailback(@PathVariable Long id) {
        User user = new User();
        user.setId(id);
        return user;
    }

HystrixCommand 表明该方法为hystrix包裹,可以对依赖服务进行隔离、降级、快速失败、快速重试等等hystrix相关功能
该注解属性较多,下面讲解其中几个

fallbackMethod 降级方法

commandProperties 普通配置属性,可以配置HystrixCommand对应属性,例如采用线程池还是信号量隔离、熔断器熔断规则等等

ignoreExceptions 忽略的异常,默认HystrixBadRequestException不计入失败

groupKey() 组名称,默认使用类名称

commandKey 命令名称,默认使用方法名

断路器执行逻辑

1.创建 HystrixCommand 或 HystrixObservableCommand

2.命令执行
execute()同步

queue() 异步

observe() 返回observable对象

toObservable() 冷observable对象

3.结果是否缓存 -> observable

4.断路器是否打开 -> fallback

5.线程池/请求队列/信号量 是否占满

6.HystrixObservableCommand.construct() 返回observable对象发射多个结果
或onError发送错误通知
或 HystrixCommand.run()
返回单一结果 或异常 onCompleted通知

7.计算断路器的健康度

8.fallback处理

9.返回成功响应

常用线程配置

若不设置组名,相同的组共用一个线程池
设置了线程池名,相同的公用一个线程池
   @HystrixCommand(fallbackMethod = "getFailback",threadPoolProperties = {
        @HystrixProperty(name = "coreSize",value = "5")
    })
coreSize 最大并发 默认10
maxQueueSize  队列大小 -1为linkedQueue
metrics.rollingStats.timeInMilliseconds 滚动时间窗口 单位毫秒 默认10秒
metrics.rollingStats.numBuckets 滚动时间窗分几个桶 默认10个桶

全局配置

hystrix.command.default.execution.isolation.strategy  
默认THREAD      
可选SEMAPHORE

hystrix.command.default.execution.timeout.enabled 
默认true

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 
默认1000毫秒

hystrix.command.default.execution.isolation.thread.interruptOnTimeout 
超时是否中断

hystrix.command.default.execution.isolation.maxConcurrentRequests 
默认10
当为信号量时,设置并发请求数 

hystrix.command.default.circuitBreaker.enabled 
默认true.
请求失败时,是否试用断路器跟踪健康指标和熔断请求

hystrix.command.default.circuitBreaker.requestVolumeThreshold 
默认20   
滚动窗口内,断路器熔断最小请求数

hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 
断路器打开后休眠时间,休眠后“半开”状态

hystrix.command.default.circuitBreaker.errorThresholdPercentage 
默认50
滚动时间窗中,请求数达到requestVolumeThreshold,失败比例超过errorThresholdPercentage,熔断打开

hystrix.command.default.metrics.rollingStats.timeInMilliseconds
默认10000(毫秒)
设置滚动窗口时间长度

hystrix.command.default.metrics.rollingStats.numBuckets
默认10
时间窗口内划分桶的数量

hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds
默认60000 (毫秒)
百分位统计的滚动窗口的持续时间

hystrix.command.default.metrics.rollingPercentile.numBuckets
默认6
百分位统计的窗口桶的数量

hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds
默认500(毫秒)
采集影响断路器状态的监控快照间隔时间

hystrix.command.default.metrics.rollingPercentile.bucketSize
默认500
每个桶保留的执行次数


hystrix.threadpool.default.coreSize 
默认10
最大并发数

hystrix.threadpool.default.maxQueueSize  
默认-1
队列大小 -1为linkedQueue


hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 
默认10000(毫秒)
滚动时间窗口 

hystrix.threadpool.default.metrics.rollingStats.numBuckets 
默认10
滚动时间窗分几个桶

声明式服务消费者(Feign)

引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8765
spring:
  application:
    name: service-feign

注解@EnableFeignClients来开启feign

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class FeignApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignApp.class, args);
    }
}

定义一个feign接口类,通过@ FeignClient(“服务名”),来指定调用哪个服务

@FeignClient(name = "provider")
public interface UserRemote {
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
     User get(@PathVariable("id") Long id);
}

web层的controller

@RestController
public class UserController {
    @Autowired
    private UserRemote userRemote;

    @GetMapping("/get/{id}")
    public User get(@PathVariable Long id) {
        return userRemote.get(id);
    }
}

支持hystrix

配置文件增加

feign.hystrix.enabled=true

修改声明

@FeignClient(name = "provider",fallback = UserRemoteFallback.class)
public interface UserRemote {
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
     User get(@PathVariable("id") Long id);
}

fallback类

@Component
public class UserRemoteFallback implements UserRemote {

    @Override
    public User get(Long id) {
        System.out.println("error");
        User user = new User();
        user.setId(id);
        return user;
    }
}

其他配置

## 指定服务配置ribbon
PROVIDER.ribbon.ConnectTimeout=500
PROVIDER.ribbon.ReadTimeout=5000
PROVIDER.ribbon.OkToRetryOnAllOperations=true
PROVIDER.ribbon.MaxAutoRetriesNextServer=2
PROVIDER.ribbon.MaxAutoRetries=1

## 请求压缩
feign.compression.request.enabled=true
feign.compression.request.mimetypes=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

feign.compression.response.enabled=true


## 日志级别
NONE
BASIC 请求方法、url、响应码、执行时间
HEADERS BASE级别+请求头、响应头
FULL 所有请求与明细,包含请求头请求体、元数据

@Bean
Logger.Level feignLoggerLevel(){
     return Logger.Level.FULL;
}

配置中心(Spring Cloud Config)

引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

配置文件application.yml

server:
  port: 7950
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: http://git.oschina.net/IMZLF/spring-config      # 配置Git仓库的地址
          username:                                           # Git仓库的账号
          password:                                           # Git仓库的密码
          search-paths:
            - foo #路径
            - bar #路径
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

Application注解@EnableConfigServer

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerEurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerEurekaApp.class, args);
    }
}

获取git上的资源信息遵循如下规则:

/{application}/{profile}[/{label}]

/{application}-{profile}.yml

/{label}/{application}-{profile}.yml

/{application}-{profile}.properties

/{label}/{application}-{profile}.properties

application : 表示应用名称,在client中通过spring.config.name配置

profile : 表示获取指定环境下配置,例如开发环境、测试环境、生产环境 默认值default,实际开发中可以是 dev、test、demo、production等

label : git标签,默认值master

如果application名称为foo,则可以采用如下方式访问:

http://localhost:8888/foo/default 
http://localhost:8888/foo/development

只要是按照上面的规则配置即可访问.

client的改造

引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

增加配置文件bootstrap.yml

spring:
  application:
    name: foo    # 对应config server所获取的配置文件的{application}
  cloud:
    config:
      profile: dev
      label: master
      discovery:
        enabled: true               
        service-id: config-server

注解@RefreshScope,引用配置属性

@RefreshScope
public class UserController {
  @Value("${profile}")
  private String profile;

  @GetMapping("/profile")
  public String profile() {
      return this.profile;
  }

测试

http://localhost:7900/profile

更新重新获取配置

http://localhost:7900/refresh

路由网关(zuul)

引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

Applicaton注解@EnableZuulProxy,开启zuul

@SpringBootApplication
@EnableZuulProxy
public class ZuulApp {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApp.class,args);
    }
}

application.yml配置文件

server:
  port: 7920
spring:
  application:
    name: zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
zuul:
  ignoredServices: '*'
  routes:
    provider: /p/**
    ribbon: /r/**
  host:
    max-total-connections: 200
    max-per-route-connections: 20

统一由zuul访问

http://localhost:7920/p/user/1
http://localhost:7920/r/get/1

ZuulFilter

s

filterOrder:filter执行顺序,通过数字指定
shouldFilter:filter是否需要执行 true执行 false 不执行
run : filter具体逻辑
filterType :filter类型,分为以下几种

pre : 请求执行之前filter
route : 处理请求,进行路由
post : 请求处理完成后执行的filter
error : 出现错误时执行的filter

zuulFilter简单实现

public class MyFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String host = request.getRemoteHost();
        System.out.println(host+request.getRequestURI());
        return null;
    }
}

Hystrix Dashboard (断路器: 仪表盘)

引入包

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

@EnableHystrixDashboard注解,开启hystrixDashboard

@EnableEurekaClient
@EnableHystrixDashboard
public class DashBoardApplication {
...

打开浏览器:访问http://localhost:6900/hystrix
输入http://localhost:8900/hystrix.stream,点击monitor

断路器聚合监控(Hystrix Turbine)

看单个的Hystrix Dashboard的数据并没有什么多大的价值,要想看这个系统的Hystrix Dashboard数据就需要用到Hystrix Turbine。
引入包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

启动类注解@EnableTurbine

@SpringBootApplication
@EnableTurbine
public class TurbineApplication {
    public static void main(String[] args) {
        SpringApplication.run(TurbineApplication.class, args);
    }
}

application.yml配置

server:
  port: 6900
spring:
  application:
    name: turbine
eureka:
  client:
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
turbine:
  aggregator:
    clusterConfig: default 
  appConfig: ribbon,feign,zuul
  clusterNameExpression: new String("default")

监控turbine流

打开:http://localhost:6900/hystrix,输入监控流localhost:6900/turbine.stream

服务链路追踪(Spring Cloud Sleuth)

引入包

<dependency>
  <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

application.yml配置

server:
  port: 7960
spring:
  application:
    name: sleuh-zipkin

client改造

application.yml配置zipkin地址

spring:
  zipkin:
    base-url: http://localhost:7960

zipkin地址

http://localhost:7960
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值