Spring cloud學習一

来源:https://www.cnblogs.com/jklixin/archive/2020/05/14/12887255.html
-Advertisement-
Play Games

SpringCLoud 總覽 [參考鏈接]: https://mp.weixin.qq.com/s/ShPlCT41Z_M0iElQTZZ07A 服務註冊/發現&註冊中心 1、Eureka 服務註冊(服務提供者)/發現(服務調用者)&註冊中心(服務中介) 服務註冊: 當 客戶端向 註冊時,它提供自身 ...


SpringCLoud

總覽

123

img

服務註冊/發現&註冊中心

1、Eureka

服務註冊(服務提供者)/發現(服務調用者)&註冊中心(服務中介)

1588323712955

  • 服務註冊:

    Eureka 客戶端向 Eureka Server 註冊時,它提供自身的元數據,比如IP地址、埠,運行狀況指示符URL,主頁等。

  • 服務續約:

    Eureka 客戶會每隔30秒(預設情況下)發送一次心跳來續約。通過續約來告知 Eureka ServerEureka 客戶仍然存在,沒有出現問題。正常情況下,如果 Eureka Server 在90秒沒有收到 Eureka 客戶的續約,它會將實例從其註冊表中刪除。

  • 服務下線

    Eureka客戶端在程式關閉時向Eureka伺服器發送取消請求。發送請求後,該客戶端實例信息將從伺服器的實例註冊表中刪除。該下線請求不會自動完成,它需要調用以下內容:DiscoveryManager.getInstance().shutdownComponent();

  • 服務剔除

    在預設的情況下,當Eureka客戶端連續90秒(3個續約周期)沒有向Eureka伺服器發送服務續約,即心跳,Eureka伺服器會將該服務實例從服務註冊列表刪除,即服務剔除。

  • 獲取註冊列表信息 Fetch Registries

    Eureka 客戶端從伺服器獲取註冊表信息,並將其緩存在本地 。 該註冊列表信息定期(每30秒鐘)更新一次。 在預設的情況下 Eureka 客戶端使用壓縮 JSON 格式來獲取註冊列表的信息。

  • 架構圖

    img

  • 步驟

    • 註冊中心

      1. pom(版本隨父項目)

        父項目

        <!--spring cloud Hoxton.SR1-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        

        註冊中心

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

        fetch-registry為true表示獲取註冊信息列表,如果該項目就是註冊中心,則為false表示不用去獲取。

        eureka:
          instance:
            hostname: eureka7001.com #eureka服務端的實例名稱
          client:
            register-with-eureka: false     #false表示不向註冊中心註冊自己。
            fetch-registry: false     #false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務
            service-url:
            #集群指向其它eureka
              # defaultZone: http://eureka7002.com:7002/eureka/
            #單機就是7001自己
              defaultZone: http://eureka7001.com:7001/eureka/
          #server:
            #關閉自我保護機制,保證不可用服務被及時踢除
            #enable-self-preservation: false
            #eviction-interval-timer-in-ms: 2000
        

        此路徑下找到hosts文件C:\Windows\System32\drivers\etc,並增加一下信息,方便直接通過功能變數名稱訪問

        # springcloud-eureka
        127.0.0.1 eureka7001.com
        127.0.0.1 eureka7002.com
        
      3. 主啟動類

        @EnableEurekaServer註解開啟Eureka

        @SpringBootApplication
        @EnableEurekaServer
        public class EurekaServerMain7001 {
            public static void main(String[] args) {
                SpringApplication.run(EurekaServerMain7001.class,args);
            }
        }
        
        
    • 客戶端

      1. pom

         <!-- eureka-client -->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
         </dependency>
        
      2. yml

        eureka:
          client:
            register-with-eureka: true #將自身註冊到eureka
            fetch-registry: true
            service-url:
              defaultZone: http://localhost:7001/eureka # http://eureka7001.com:7001/eureka/ 也可以
              # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
        
      3. 啟動類

        @EnableEurekaClient

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

2、Consul

3、Zookeeper


服務介面調用

OpenFeign

OpenFeign 直接內置了 Ribbon。

RestTemplateSpring提供的一個訪問Http服務的客戶端類 。例如以下例子,我們就能通過/judge路徑訪問到http://localhost:8081//service1

@Autowired
private RestTemplate restTemplate;
// 這裡是提供者A的ip地址,但是如果使用了 Eureka 那麼就應該是提供者A的名稱
privatestaticfinal String SERVICE_PROVIDER_A = "http://localhost:8081";

@PostMapping("/judge")
public boolean judge(@RequestBody Request request) {
    String url = SERVICE_PROVIDER_A + "/service1";
    return restTemplate.postForObject(url, request, Boolean.class);
}

使用有些麻煩。OpenFeign能做到向 功能變數名稱和IP地址的映射一樣進行服務間的調用

  • 實現

    • 消費端
    1. pom

       <!--openfeign-->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-openfeign</artifactId>
              </dependency>
      
    2. yml

      將預設等待時間延長,預設為一秒,因為連接遠程伺服器已經多個項目直接的調用容易造成超時。

      #設置feign客戶端超時時間(OpenFeign預設支持ribbon)
      ribbon:
      #指的是建立連接所用的時間,適用於網路狀況正常的情況下,兩端連接所用的時間
        ReadTimeout: 5000
      #指的是建立連接後從伺服器讀取到可用資源所用的時間
        ConnectTimeout: 5000
      
    3. 主啟動類

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

      @Component
      @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
      public interface PaymentFeignService
      {
          @GetMapping(value = "/payment/get/{id}")
          public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
      
          @GetMapping(value = "/payment/feign/timeout")
          public String paymentFeignTimeout();
      }
      
    5. Controller

      Controller 就可以像原來調用 Service 層代碼一樣調用它了。

      @RestController
      @Slf4j
      public class OrderFeignController
      {
          @Resource
          private PaymentFeignService paymentFeignService;
      
          @GetMapping(value = "/consumer/payment/get/{id}")
          public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
          {
              return paymentFeignService.getPaymentById(id);
          }
      
          @GetMapping(value = "/consumer/payment/feign/timeout")
          public String paymentFeignTimeout()
          {
              // OpenFeign客戶端一般預設等待1秒鐘
              return paymentFeignService.paymentFeignTimeout();
          }
      }
      	
      
    • 提供端

      實現@FeignClient註解標註類的路徑映射即可


負載均衡

Ribbon(蝴蝶結)

它是在消費者端進行的負載均衡 。

  • RoundRobinRule:輪詢策略。Ribbon預設採用的策略。若經過一輪輪詢沒有找到可用的provider,其最多輪詢 10 輪。若最終還沒有找到,則返回 null。(預設
  • RandomRule: 隨機策略,從所有可用的 provider 中隨機選擇一個。
  • RetryRule: 重試策略。先按照 RoundRobinRule 策略獲取 provider,若獲取失敗,則在指定的時限內重試。預設的時限為 500 毫秒。

實現:

  1. 配置類

    @Configuration
    public class ApplicationContextConfig
    {
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate()
        {
            return new RestTemplate();
        }
    }
    

    註意:先啟動Eureka,再啟動提供端,再啟動消費端

自定義負載均衡演算法

  1. 實現 IRule 介面

  2. 修改配置文件或者自定義 Java Config 類。

  3. 不能與啟動類在同級包,也不能在啟動類同級包的子包下。

    以下啟動類在com.lx

    自定義負載均衡在com.myrule

    @Configuration
    public class MySelfRule
    {
        @Bean
        public IRule myRule()
        {
            return new RandomRule();//定義為隨機
        }
    }
    
    

服務熔斷降級

Hystrix(豪豬獸)

Hystrix是一個庫,可通過添加等待時間容限和容錯邏輯來幫助您控制這些分散式服務之間的交互。Hystrix通過隔離服務之間的訪問點,停止服務之間的級聯故障並提供後備選項來實現此目的,所有這些都可以提高系統的整體彈性。

在微服務場景中,通常會有很多層的服務調用。如果一個底層服務出現問題,故障會被向上傳播給用戶。我們需要一種機制,當底層服務不可用時,可以阻斷故障的傳播。這就是斷路器的作用。他是系統服務穩定性的最後一重保障。

在springcloud中斷路器組件就是Hystrix。Hystrix也是Netflix套件的一部分。他的功能是,當對某個服務的調用在一定的時間內(預設10000ms),有超過一定次數(預設20次)並且失敗率超過一定值(預設50%),(更多詳情見HystrixCommandProperties類),該服務的斷路器會打開。返回一個由開發者設定的fallback。

fallback可以是另一個由Hystrix保護的服務調用,也可以是固定的值。fallback也可以設計成鏈式調用,先執行某些邏輯,再返回fallback。

Hystrix的作用

  1. 對通過第三方客戶端庫訪問的依賴項(通常是通過網路)的延遲和故障進行保護和控制。
  2. 在複雜的分散式系統中阻止級聯故障。
  3. 快速失敗,快速恢復。
  4. 回退,儘可能優雅地降級。
  5. 啟用近實時監控、警報和操作控制。

1、服務降級

情景:

  1. 程式運行異常
  2. 超時
  3. 服務熔斷觸發服務降級
  4. 線程池/信號量也會導致服務降級

實現:

  1. pom

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  2. 主啟動

    @SpringBootApplication
    @EnableEurekaClient
    @EnableCircuitBreaker
    public class PaymentHystrixMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentHystrixMain8001.class,args);
        }
    
        /**
         *此配置是為了服務監控而配置,與服務容錯本身無關,springcloud升級後的坑
         *ServletRegistrationBean因為springboot的預設路徑不是"/hystrix.stream",
         *只要在自己的項目里配置上下麵的servlet就可以了
         */
        @Bean
        public ServletRegistrationBean getServlet() {
            HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
            registrationBean.setLoadOnStartup(1);
            registrationBean.addUrlMappings("/hystrix.stream");
            registrationBean.setName("HystrixMetricsStreamServlet");
            return registrationBean;
        }
    }
    
  3. service

    /**
      * @Description: 正常訪問
      * @Param0: id
      **/
    public String paymentInfo_OK(Integer id)
    {
        return "線程池:  "+Thread.currentThread().getName()+"  paymentInfo_OK,id:  "+id+"\t"+"O(∩_∩)O哈哈~";
    }
    
    /**
      * @Description: 超時訪問/訪問異常,2s
      * @Param0: id
      **/
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",
                    commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")})
    public String paymentInfo_TimeOut(Integer id)
    {
        int timeSleep=3000;
        try { TimeUnit.MILLISECONDS.sleep(timeSleep); } catch (InterruptedException e) { e.printStackTrace(); }
        return "線程池:  "+Thread.currentThread().getName()+" id:  "+id+"\t"+"O(∩_∩)O哈哈~"+"  耗時(毫秒): "+timeSleep;
    }
    /**
      * @Description: 超時處理
      **/
    public String paymentInfo_TimeOutHandler(Integer id)
    {
        return "線程池:  "+Thread.currentThread().getName()+"  8001系統繁忙,請稍後再試,id:  "+id+"\t"+"o(╥﹏╥)o";
    }
    /**
      * @Description: 訪問異常
      * @Param0: id
      **/
    @HystrixCommand(fallbackMethod = "paymentInfo_ExceptionHandler")
    public String paymentInfo_Exception(Integer id)
    {
        int i=10/0;
        return "線程池:  "+Thread.currentThread().getName()+" id:  "+id+"\t"+"O(∩_∩)O哈哈~"+"  結果 "+i;
    }
    /**
      * @Description: 異常處理
      **/
    public String paymentInfo_ExceptionHandler(Integer id)
    {
    
        return "線程池:  "+Thread.currentThread().getName()+"  8001運行報錯,請稍後再試,id:  "+id+"\t"+"o(╥﹏╥)o";
    }
    
  4. 問題:

    1. 一個方法匹配一個fallback指定的方法
    2. 處理異常方法與我們的主要邏輯代碼混合在一起
  5. 改善

    在調用端controller類上加上@DefaultProperties註解,指定整個類的全局降級處理方法

    @RestController
    @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
    public class OrderOpenFeignController {
    
        @Resource
        PaymentService paymentService;
    
        @Resource
        PaymentHystrixService paymentHystrixService;
    
        @GetMapping("/consumer/payment/get/{id}")
        public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
            return paymentService.getPaymentByid(id);
        }
    
        @GetMapping("/consumer/payment/hystrix/ok/{id}")
        public String paymentInfo_OK(@PathVariable("id") Integer id)
        {
            String result = paymentHystrixService.paymentInfo_OK(id);
            System.out.println("*****result: "+result);
            return result;
        }
    
        @GetMapping("/consumer/payment/hystrix/timeout/{id}")
       /* @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
        })*/
        //使用全局處理之後寫下麵的註解,不加屬性代表使用預設的全局處理方法
        @HystrixCommand
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
        {
            String result = paymentHystrixService.paymentInfo_TimeOut(id);
            System.out.println("*****result: "+result);
            return result;
        }
    
        public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){
            return "timeout";
        }
    
        // 下麵是全局fallback方法
        public String payment_Global_FallbackMethod()
        {
            return "Global異常處理信息,請稍後再試,/(ㄒoㄒ)/~~";
        }
    
    }
    

2、服務熔斷

類比保險絲達到最大服務訪問後,直接拒絕訪問,拉閘限電,然後調用服務降級的方法並返回友好提示 。

服務的降級->進而熔斷->恢復調用鏈路

實現:

  1. ​ service

    //=====服務熔斷
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
    
    
        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否開啟斷路器
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 請求次數
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 時間視窗期
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失敗率達到多少後跳閘
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id)
    {
        if(id < 0)
        {
            throw new RuntimeException("******id 不能負數");
        }
        String serialNumber = IdUtil.simpleUUID();
    
        return Thread.currentThread().getName()+"\t"+"調用成功,流水號: " + serialNumber;
    }
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
    {
        return "id 不能負數,請稍後再試,/(ㄒoㄒ)/~~   id: " +id;
    }
    
  2. 測試

    通過改變參數訪問,當使用負數訪問是會觸發服務降級,多次降級後服務會自動打開熔斷(表現為即使使用正數訪問仍然是降級處理),之後逐漸恢復正常處理。

3、服務監控

實現:

  1. pom

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

    9001埠

  3. 主啟動類

    @EnableHystrixDashboard

  4. 要求,所有提供服務端都添加actuator

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
     </dependency>
    
  5. 此版本需要配置路徑,才能用一下圖片路徑訪問

    @Bean
        public ServletRegistrationBean getServlet() {
            HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
            registrationBean.setLoadOnStartup(1);
            registrationBean.addUrlMappings("/hystrix.stream");
            registrationBean.setName("HystrixMetricsStreamServlet");
            return registrationBean;
        }
    

1588410050258

1588410010293

註意:每個顏色的數字對應右上方每個屬性,例如,綠色代表成功次數。

服務網關

  • 網關職責:

      	<img src="https://gitee.com/jklixin/images/raw/master/cloud/aHR0cDovL2Nvcy5yYWluMTAyNC5jb20vbWFya2Rvd24vaW1hZ2UtMjAxOTEwMDgxNjAzMjUwMjEucG5n.jpg" alt="img" style="zoom: 50%;" /> 
    
  • 網關分類與功能:

    img

1、Gateway

為微服務架構提供一種簡單而有效的統一的API路由管理方式

img

1589353262774

  • 實現

    1. pom

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-gateway</artifactId>
      </dependency>
      
    2. yml

      server:
        port:  9527
      spring:
        application:
          name: cloud-gateway
        cloud:
          gateway:
            discovery:
              locator:
                enabled: true #開啟從註冊中心動態創建路由的功能,利用微服務名進行路由
            routes:
              - id: payment_routh #路由的ID,沒有固定規則但要求唯一,建議配合服務名
                # uri: http://localhost:8001 #匹配後提供服務的路由地址
                uri: lb://cloud-payment-service #匹配後提供服務的路由地址
                predicates:
                  - Path=/payment/** # 斷言,路徑相匹配的進行路由
      eureka:
        instance:
          hostname: cloud-gateway-service
        client: #服務提供者provider註冊進eureka服務列表內
          service-url:
            register-with-eureka: true
            fetch-registry: true
            defaultZone: http://eureka7001.com:7001/eureka
      
    3. 主啟動

      @SpringBootApplication
      @EnableEurekaClient
      public class GatewayMain9527 {
          public static void main(String[] args) {
              SpringApplication.run(GatewayMain9527.class,args);
          }
      }
      
      
    4. 測試:

      通過埠9527訪問服務名為cloud-payment-service的服務,路徑匹配時訪問成功

路由轉發

  1. 時間匹配

    Predicate 支持設置一個時間,在請求進行轉發的時候,可以通過判斷在這個時間之前或者之後進行轉發。

    predicates:
             - After=2020-01-20T06:06:06+08:00[Asia/Shanghai]
    

    2020/01/20之後訪問才會進行轉發到對應的服務, Before 同理

  2. Cookie匹配

    Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name , 一個是正則表達式,

    predicates:
             - Cookie=ityouknow, kee.e
    

    測試:curl http://localhost:9527 --cookie "ityouknow=kee.e",匹配成功

  3. 請求頭匹配

    Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行。

     predicates:
            - Header=X-Request-Id, \d+
    

    測試1 curl http://localhost:9527 -H "X-Request-Id:1234" 匹配成功

    測試2 curl http://localhost:9527 -H "X-Request-Id:sfsg" 匹配失敗

  4. Host匹配

    Host Route Predicate 接收一組參數,一組匹配的功能變數名稱列表,這個模板是一個 ant 分隔的模板,用.號作為分隔符。它通過參數中的主機地址作為匹配規則。

     predicates:
            - Host=**.ityouknow.com
    

    測試 curl http://localhost:9527 -H "Host: www.ityouknow.com" 匹配成功

  5. 請求方式匹配

     predicates:
            - Method=GET
    

    curl 預設是以 GET 的方式去請求

    測試 curl -X POST http://localhost:9527 匹配失敗

  6. 請求參數匹配

    • Query Route Predicate 支持傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。
     predicates:
            - Query=smile
    

    只要求情中包含該屬性即可匹配

    測試 curl localhost:9527?smile=x&id=2 匹配成功。

    • 將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配
     predicates:
            - Query=keep, pu.
    

    當請求中包含 keep 屬性並且參數值是以 pu 開頭的長度為三位的字元串才會進行匹配和路由。

    測試1 curl localhost:9527?keep=pub 匹配成功

    測試2 curl localhost:9527?keep=pubx 匹配失敗

  7. 請求ip匹配

    Predicate 也支持通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號 (IPv4 或 IPv6) 字元串的列表(最小大小為 1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網掩碼)。

     predicates:
            - RemoteAddr=192.168.1.1/24
    

    請求的遠程地址是 192.168.1.10,則此路由將匹配

  8. 組合匹配

    • 需要滿足所有斷言條件才會被轉發
    • 當滿足多個路由時。先匹配先轉發原則

Filter

下例中表示當含有uname屬性是允許訪問。

@Component
public class FilterConfig implements GlobalFilter,Ordered{

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("進入過濾器");
        String uname=exchange.getRequest().getQueryParams().getFirst("uname");
        if(uname==null){
            //請求路徑中沒有該屬性值
            System.out.println("拒絕訪問");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        //存在,放行
        return chain.filter(exchange);
    }

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

測試: http://localhost:9527/payment/lb?uname=z3 訪問成功

服務配置中心

為分散式系統中的外部配置提供伺服器和客戶端支持。方便部署與運維。有客戶端、服務端。

服務端也稱分散式配置中心,是一個獨立的微服務應用,用來連接配置伺服器併為客戶端提供獲取配置信息,加密/解密信息等訪問介面。

客戶端則是通過指定配置中心來管理應用資源,以及與業務相關的配置內容,併在啟動的時候從配置中心獲取和載入配置信息。預設採用 git,並且可以通過 git 客戶端工具來方便管理和訪問配置內容。

優點:

  • 集中管理配置文件
  • 不同環境不同配置,動態化的配置更新
  • 運行期間,不需要去伺服器修改配置文件,服務會想配置中心拉取自己的信息
  • 配置信息改變時,不需要重啟即可更新配置信息到服務
  • 配置信息以 rest 介面暴露

實現:

  1. 服務端

    1. pom

      <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-config-server</artifactId>
              </dependency>
      
    2. yml

      spring:
        application:
          name:  cloud-config-server #註冊進Eureka伺服器的微服務名
        cloud:
          config:
            server:
              git:
                # uri: [email protected]:zzyybs/springcloud-config.git #GitHub上面的git倉庫名字
                uri: https://gitee.com/jklixin/springcloud-config.git #Gitee上面的git倉庫名字
              ####搜索目錄
                search-paths:
                  - springcloud-config
            ####讀取分支
            label: master
      
    3. 啟動類

      @EnableConfigServer

      @SpringBootApplication
      @EnableConfigServer
      public class ConfigMain3344 {
          public static void main(String[] args) {
              SpringApplication.run(ConfigMain3344.class,args);
          }
      }
      
  2. 客戶端

    1. pom

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

      spring:
        application:
          name: cloud-config-client
        cloud:
          config:
            lable: master 
            name: config  #需要從github上讀取的資源名稱,註意沒有yml尾碼名
            profile: dev #本次訪問的配置項
            uri: http://localhost:3344 #配置服務端,本微服務啟動後先去找3344號服務,通過SpringCloudConfig獲取GitHub的服務地址
      
    3. controller

      @RestController
      //@RefreshScope
      public class ConfigController {
      
          @Value("${config.info}")
          String info;
      
          @GetMapping("/configInfo")
          public String getConfigInfo(){
              return info;
          }
      }
      

訪問方式:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

1588476129348

1588476151356

問題: 更改gitee上的內容,服務端更新成功,但是客戶端並未更新成功

動態刷新

解決:

  1. 客戶端引入actuator依賴

  2. 暴露監控端點

    # 暴露監控端點
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
  3. @refreshScope業務類Controller修改

  4. 需要運維發送Post請求刷新3355

    curl -X POST "http://localhost:3355/actuator/refresh"
    

問題: 多個客戶端如何實現動態刷新


消息匯流排

Bus

Bus支持兩種消息代理:RabbitMQ和Kafka

廣播

實現

  • 服務端

    1. 添加bus-amqp依賴

       <!--添加消息匯流排RabbitMQ支持-->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
              </dependency>
      
    2. 配置rabbitmq相關屬性

        #rabbitmq相關配置
        rabbitmq:
          host: 123.56.16.54
          port: 5672
          username: guest
          password: guest
      
    3. 暴露刷新埠

      # 暴露bus刷新的端點
      management:
        endpoints:
          web:
            exposure:
              include: 'bus-refresh'
      
  • 客戶端

    1. 添加bus-amqp依賴
    2. 配置rabbitmq相關屬性

測試:

  1. 更改配置文件

  2. 刷新

    http://localhost:3344/config-dev.yml 一致

    http://localhost:3355/configInfo 不一致

  3. 發送請求刷新 curl -X POST "http://localhost:3344/actuator/bus-refresh"

    1588477143566

  4. 刷新

    http://localhost:3355/configInfo 一致

    http://localhost:3366/configInfo 一致

定點通知

實現: 公式:http://localhost:3344/actutor/bus-refresh/{destination}

測試: curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"

http://localhost:3355/configInfo 一致

http://localhost:3366/configInfo 不一致


消息驅動

Stream

屏蔽底層消息中間件的差異,降低切換成本,統一消息的編程模型


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • WebSocket跟常規的http協議的區別和優缺點這裡大概描述一下 一、websocket與http http協議是用在應用層的協議,他是基於tcp協議的,http協議建立鏈接也必須要有三次握手才能發送信息。http鏈接分為短鏈接,長鏈接,短鏈接是每次請求都要三次握手才能發送自己的信息。即每一個r ...
  • 一、簡介 dataclasses是python新的內置庫,也是一種新的特性吧(對我來說吧,因為我很少用到) 具體內容官方文檔也有: 二、使用 在python中創建一個類,我們需要寫\_\_init\_\_方法進行初始化對象操作,需要對對象進一步說明的話,最好寫一個\_\_repr\_\_方法,這樣我 ...
  • 我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 136. 只出現一次的數字 題目 給定一個非空整數數組,除了某 ...
  • 昨天在Python學習群里有位路人甲問了個Python函數中關於形參和實參一個很基礎的問題,雖然很基礎,但是對於很多小白來說不一定簡單,反而會被搞得稀里糊塗。人生苦短,我用Python。 為瞭解答大家的這個疑惑,小編在此舉個慄子,希望大家能夠徹底的理解實參和形參在Python中的用法。 首先,大家一 ...
  • JVM 參數 1. 標準參數:不會隨著jdk版本的變化而變化。比如:java version、java help 2. 非標準參數:隨著JDK版本的變化而變化。 X參數【用的較少】非標準參數,也就是在JDK各個版本中可能會變動 XX參數【用的最多:JVM調優額Debug】非標準化參數,相對不穩定。 ...
  • 一、基礎架構 概覽 我們平時說的棧是指的Java棧,native method stack 裡面裝的都是native方法 細節架構圖 二、類載入器 1、類的載入 方法區並不是存放方法的區域,其是存放類的描述信息(==模板==)的地方 Class loader只是負責class文件的載入,相當於快遞員 ...
  • 這是一個Spring Cloud系列文章,它並不會講解所有的知識點,它只是基於微服務的場景來**逐步介紹**常見組件的作用和意義,以及場景組件的整合。對於每個組件的知識並不會講解太多,只講常見的,目的是儘可能快速的對Spring Cloud的常用組件有一個基礎的認知,有了認知之後,你就可以基於你面對... ...
  • 本來安裝frida就兩個命令就搞定的事 pip install frida pip install frida-tools    但是死活給整了一兩個小時 一執行pip命令,不是報 如下錯: WARNING: Retrying (Retry(total=4, connect=... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...