1. 程式人生 > >springcloud 入門筆記-1

springcloud 入門筆記-1

1.安裝sts(spring tool suite)

<!-- 熱部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

部署後項目前有[devtools],修改無需重啟
3.boot封裝了json,返回的物件都是json格式

2.依賴和整合

3.自定義封裝

可以是重複的類,也可是重複的feign介面

4.ribbon預設的負載均衡策略

預設是輪詢測略,可自定義為隨機策略

microservice-provider:  ##config ribbon   
  ribbon: 
    eureka: 
      enabled: false   
    listOfServers: localhost:8000, localhost:8002,localhost:8003 #假設provider有3臺instance埠分別是8000 8002 8003  
    ServerListRefreshInterval
: 15000 #設定服務列表重新整理時間間隔

注意:
1.自定義配時,@Configuration包和@ComponentsScan包不應重疊
2.使用RestTemplate時,想要獲得一個List時,應使用陣列,而不應該直接使用List

5.feign集成了ribbon和hystrix

1.feign是webservice的客戶端,
2.預設@FeignClient(name=”“)不寫預設為name,
不建議用service-id,看原始碼知過時了,

    @Deprecated
    String serviceId() default ""
;

其中引數還有個屬性為url,注意有url時必須有name
最重要的話: (官文原話)
springcloud根據需要使用FeignClientConfiguration為每個命名的客戶端建立一個新的整體作為ApplicationContext.包含feign Decoder,feign Encoder,feign Contract
即@FeignClient(“”)建立了一個子容器 ,包含日誌,解碼器,編碼器,契約(是springmvcContract,故可以支援mvc註解)
這裡寫圖片描述
3.有6個坑
3.1.介面中的方法必須用@RequestMapping(value= method=…),不能使用@GetMaping(不支援),否則無法啟動
3.2.介面中的方法中往往有引數,一定不能省了@PathVariable(“”)設定value,否則報引數為0
3.3.介面中的方法中引數如果是物件,只能設定為Post方法,設定為get方法報錯:需要get方法,即使你設定的就是get.
如果一定要用get,只能將物件屬性全設定為引數,使用@RequestParam(“id”) int id,@RequestParam(“name”) string name…
3.4.在controller類中的註解上,如果不使用thymeleaf,則可用@RestController,對應方法上使用@GetMapping、@PostMapping;
如果使用thymeleaf,必須用@Controller,對應@RequestMaping…否則返回無法跳轉到頁面,只會返回物件
3.5.使用@Configuration時不要同時註解@ComponentsScan,有衝突
3.6 .啟動應用報timeout錯誤時配置:

解決第一次請求報錯超市異常(ms)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
或者
hystrix.command.default.execution.timout.enabled: false

6.自定義feign

使用@FeignClient的configuration屬性,指定feign的配置類:

@FeignClient(name = "microservice-provider-user", configuration = FeignConfiguration.class)
public interface UserFeignClient {
  /**
   * 使用feign自帶的註解@RequestLine
   * @see https://github.com/OpenFeign/feign
   * @param id 使用者id
   * @return 使用者資訊
   */
  @RequestLine("GET /{id}")
  public User findById(@Param("id") Long id);
}

注意其中的註解格式,然後是配置類:

/**
 * 該類為Feign的配置類
 * 注意:該不應該在主應用程式上下文的@ComponentScan中。
 */
@Configuration
public class FeignConfiguration {
  /**
   * 將契約改為feign原生的預設契約。這樣就可以使用feign自帶的註解了。
   * @return 預設的feign契約
   */
  @Bean
  public Contract feignContract() {
    return new feign.Contract.Default();
  }
}

目錄結構為:
這裡寫圖片描述
上面的方式只是為UserFeignClient 介面設定了feign的配置類,如果還有其他的介面怎麼辦?
目前的方法是建立第二個介面類,對應設定第二個配置類。
feign的功能很多
1.壓縮GZIP
feign.compression.request.enabled=true
feign.compression.response.enabled=true
2.日誌: yml中配置,使用介面類全類名:

logging:
  level:
    com.xx.UserFeignClient: DEBUG

同時在配置類中新增,四個級別NONE,BASIC,HEADERS,FULL

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

7.eureka常見問題

7.1 eureka介面的enviroment和datacenter配置

eureka:
  enviroment: product #eureka中環境
  datacenter: cloud #eureka中datacenter,使用cloud,這樣eureka將會知道是在AWS雲上

7.2 eureka的自我保護提示
eureka的自我保護模式主要用於在一組客戶端和eureka伺服器之間存在網路分割槽的情況下的保護,在這些情況下,伺服器嘗試保護其已有的資訊。就是說即使某個服務停止了,註冊中心依然不剔除它。但是在開發階段,這個不是我們需要的。
注意的是使用sts,則保護模式會失效,因為在點選停止的時候,sts會呼叫springboot的shundown hook,這個鉤子會向eureka server主動下線。
如果要配置關閉自我保護,如下:

server端:
    eureka.server.enable-self-preservation  #設為false,關閉自我保護模式
    eureka.server.eviction-interval-timer-in-ms #清理間隔(ms,預設60*1000)
client端:
    eureka.client.healthcheck.enabled = true    #開啟健康檢查(actuator)
    eureka.instance.lease-renewal-interval-in-seconds=10   #租期更新時間間隔(預設30s)
    eureka.instance.lease-expiration-duration-in-seconds =30  #租期到期時間(預設90s)

示例如下:

eureka: 
  instance: 
    ip-address: 172.x.x.x
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 10 # 租期更新時間間隔(預設30s)
    lease-expiration-duration-in-seconds: 30 #租期到期時間(預設90s)
  client: 
    serviceUrl: 
      defaultZone: http://172.x.x.x:9079/eureka/
    register-with-eureka: true
    fetch-registry: true
    healthcheck: 
      enabled: true #開啟健康檢查(actuator)
  server:
    enable-self-preservation: false #設為false,關閉自我保護模式
    eviction-interval-timer-in-ms: 4000 #清理間隔(ms,預設60*1000)

注意
1.更改eureka更新頻率將打破伺服器的自我保護功能
2.生產階段不要更改eureka的配置,否則保護模式失效

8.feign的hystrix支援

Hystrix支援回退的概念:當斷路器開啟或者出現錯誤時執行的預設程式碼路徑,要為給定的@FeignClient啟用回退,請將fallback屬性設定為實現回退的類名。
全域性開啟或禁用hystrix:

feign.hystrix.enabled = false

前面提到feign下整合有ribbon和hystrix,已經整合,只需要在feign中配置fallback即可

/**
 * Feign的fallback測試
 * 使用@FeignClient的fallback屬性指定回退類
 */
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}
/**
 * 回退類FeignClientFallback需實現Feign Client介面
 * FeignClientFallback也可以是public class,沒有區別
 */
@Component
class FeignClientFallback implements UserFeignClient {
  @Override
  public User findById(Long id) {
    User user = new User();
    user.setId(-1L);
    user.setUsername("預設使用者");
    return user;
  }
}

注意使用@Component時,不用配@ComponentScan,啟動類有整合

怎樣禁用單個FeignClient的Hystrix?
如同上面提到的,當有多個FeignClient介面類,怎麼禁用某個的hystrix呢?
在configuration類中加入:

  @Bean
  @Scope("prototype")
  public Feign.Builder feignBuilder(){
      return Feign.builder();
  }

之所以可以如此是因為

Feign.Builder feignBuilder: HystrixFeign.Builder

預設就是使用Feign.Builder 支援hystrixFeign。

9.feign的hystrix fallbacks

如果你需要在觸發fallback觸發器時返回一個錯誤原因,你可以使用fallbackFactory:

@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}
/**
 * UserFeignClient的fallbackFactory類,該類需實現FallbackFactory介面,並覆寫create方法
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
  private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
  @Override
  public UserFeignClient create(Throwable cause) {
    return new UserFeignClient() {
      @Override
      public User findById(Long id) {
        // 日誌最好放在各個fallback方法中,而不要直接放在create方法中。
        // 否則在引用啟動時,就會列印該日誌。
        // 詳見https://github.com/spring-cloud/spring-cloud-netflix/issues/1471
        FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
        User user = new User();
        user.setId(-1L);
        user.setUsername("預設使用者");
        return user;
      }
    };
  }
}