SpringCloud 2.2.0 搭建學習

 

目錄

一.SpringCloud簡介

二.常用組成

三.代碼實現

1.註冊中心Eureak

2.客戶端client

3.配置中心Config

4.應用監控與管理:actuator (可以放在任何一個springboot項目上)

5.客戶端之間的調用feign(Feign 是對 Ribbon的封裝,使用註解的方式,調用起來更簡單。。。 也是主流的方式~)

6.客戶端之間的調用Ribbon(Ribbon 是使用 restTemplate 進行調用,並進行客戶端負載均衡。)

7.熔斷器:hystrix(熔斷只是作用在服務調用這一端,與feign一塊使用)

8.網關



一.SpringCloud簡介

springcloud是微服務架構,他是由多個獨立項目集合而成的,每個項目都是獨立的,各自進行自己的迭代和版本發佈。所以springcloud不方便使用版本號來管理,而是使用版本名。以避免和子項目版本號的衝突。

二.常用組成

  1. 註冊中心:eureak(除了eureak springcloud還提供了Consul服務中心)
  2. 客戶端:client
  3. 配置中心:config
  4. 應用監控與管理:actuator
  5. 客戶端之間的調用:feign
  6. 客戶端負載均衡:ribbon
  7. 熔斷器:hystrix
  8. 服務網關: Zuul,Geteway 
  9. 消息驅動:Stream
  10. 服務鏈路追蹤:Zipkin
  11. 消息總線:Bus
  12. 批量任務:Task
  13. 授權認證:SpringSecurity

三.代碼實現

1.註冊中心Eureak

  • 創建一個springboot項目,裏面啥組件都不許需要添加,或者用默認的eureak組件,我是搭建了一空的架子,一個一個添
  • 添加pom
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>



-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 在啓動類添加註解,來標識這是一個eureak服務
@EnableEurekaServer
  • 配置yml,單機配置,後面有其他的會在下面添加
server:
  port: 8010

spring:
  application:
    name: eureka-server

eureka:
  #指定主機名稱
  instance:
    hostname: 127.0.0.1
  #server一定程度上也是client,互爲client,
  client:
    #由於自己就是服務器,不需要註冊到自己
    register-with-eureka: false
    #由於自己就是服務器,不需要從服務器獲取註冊信息
    fetch-registry: false
    #服務地址
    service-url:
      defaultZone: http://127.0.0.1:8010/eureka/
  • 啓動訪問:http://localhost:8010,出現下面的界面說明基本eureak搭建好了

  • 添加security賬號認證,在pom中添加security包
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>
  • 在yml中加入
server:
  port: 8010


spring:
  application:
    name: eureka-server
  security:
    basic:
      enabled: true
    user:
      name: herbert
      password: 123456

eureka:
  #指定主機名稱
  instance:
    hostname: 127.0.0.1
  #server一定程度上也是client,互爲client,
  client:
    #由於自己就是服務器,不需要註冊到自己
    register-with-eureka: false
    #由於自己就是服務器,不需要從服務器獲取註冊信息
    fetch-registry: false
    #服務地址
    service-url:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/
  • 加入一個CSRF禁用問題,這是一個坑,大坑,查資料瞭解到新版(Spring Cloud 2.0 以上)的security默認啓用了csrf檢驗,要在eurekaServer端配置security的csrf檢驗爲false
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().ignoringAntMatchers("/eureka/**");
        super.configure(http);
    }
}

 

2.客戶端client

  • 創建一個springboot項目,裏面啥組件都不許需要添加,或者用默認的eureak組件,我是搭建了一空的架子,一個一個添
  • 添加pom
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>


-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 在啓動類添加以下註解標識客戶端
@EnableEurekaClient
  • 配置yml文件,現在連接的是沒有security的服務端
server:
  port: 8005

spring:
  application:
    name: client-student-one

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8010/eureka/
  • 訪問服務端eureak地址:http://localhost:8010,會出現下面紅線的地方

  • 配置yml文件,現在連接的是有security的服務端
server:
  port: 8005

spring:
  application:
    name: client-student-one

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/
  • 客戶端自此配置完成,可以多配置幾個客戶端,方便後期的學習,我這邊還添加了
server:
  port: 8006

spring:
  application:
    name: client-student-two

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/


---------------------------------------------------------------------------------



server:
  port: 8007

spring:
  application:
    name: client-student-three

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/

3.配置中心Config

  • 添加pom
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>


-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 再啓動類加入以下配置來標記是配置中心
@EnableConfigServer
  • 配置yml,看下圖我的幾個配置

(1)application-client.yml

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/

(2)application-eureka.yml

server:
  port: 8010


spring:
  application:
    name: eureka-server
  security:
    basic:
      enabled: true
    user:
      name: herbert
      password: 123456

eureka:
  instance:
    hostname: 127.0.0.1
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/

(3)application.yml

server:
  port: 8102

spring:
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/server/
  application:
    name: eureka-config
  profiles:
    active: native
  • eureka config-server就搭建完了,我們來測試一下,項目跑起來,輸入:http://127.0.0.1:8102/server/client,如下圖就搭建完了

  • 或者輸入:http://127.0.0.1:8102/server/application-client.yml出現以下內容,就說明搭建成功

  • 下一步就是讓客戶端鏈接我們的服務中心,這裏有一個大坑,就是springboot讀取配置文件的順序,這裏要把application.yml改成bootstrap.yml  , 我這裏將application.yml改成了bootstrap.yml

(1)加入pom的包

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

(2)配置bootstrap.yml

spring:
  cloud:
    config:
      label: server
      profile: client
      uri: http://localhost:8102
server:
  port: 8007

將所有的springboot都修改了,連接一個config,修改完後可以將config-server中的配置加載在其他服務裏面

 

4.應用監控與管理:actuator (可以放在任何一個springboot項目上)

  • 新建一個springboot項目,查看一下
  • 添加pom
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  •  修改yml端口爲 8011
server:
  port: 8011
management:
  endpoints:
    web:
      exposure:
        include: "*" #暴露所有端點 默認是info,health
{"status":"UP"} 是健康狀態

具體可以參考一下下面的接口

其他的具體操作可以參考:https://blog.csdn.net/wya1993/article/details/80540981

 

5.客戶端之間的調用feign(Feign 是對 Ribbon的封裝,使用註解的方式,調用起來更簡單。。。 也是主流的方式~)

  • 我們用客戶端2通過feign調用客戶端1的接口

在客戶端2中引入pom

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

加入feign啓動註解,表示我是一個feign客戶端

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class ClientApplication {

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

}

調用客戶1的註解,首先在客戶端1寫一個接口

 客戶端2開始調用這個接口了,通過接口調用,其中@FeigenClient裏面的迷你必須是註冊中心的名字,在http://localhost:8010/eureak服務中心查找

 最後就是在controller調用這個接口,調用成功

 訪問這個接口調用成功

6.客戶端之間的調用Ribbon(Ribbon 是使用 restTemplate 進行調用,並進行客戶端負載均衡。)

  • 我們還是用客戶端2和客戶端1做測試,首先在客戶端1中寫一個接口爲

  •  我們用客戶端2通過ribbon調用客戶端1的ribbon接口

1.在客戶端2添加pom


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

 

2.我們初始化restTemplate (RestTemplate 是由 Spring Web 模塊提供的工具類,與 SpringCloud 無關,是獨立存在的因 SpringCloud 對 RestTemplate 進行了一定的擴展,所以 只注入實例化時被@LoadBalanced修飾的實例。)再啓動類中加入

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

3.調用客戶端1的ribbon接口

這就是ribbon的調用,個人覺得還不如用feign

 

7.熔斷器:hystrix(熔斷只是作用在服務調用這一端,與feign一塊使用)

  • 我們繼續用客戶端2調用客戶端1的接口,使用feign+hystrix

1.現在客戶端1寫一個接口

2.在客戶端2的yml中開啓hystrix

feign:
  hystrix:
    enabled: true

3.因爲hystrix和feign一塊用,一個客戶端不能出現兩個接口連接同一個feign,所以我們在上面的feign上修改

修改FeignService接口

添加ProductClientFeignHystrix類

@Component
public class ProductClientFeignHystrix implements FeignService {

    @Override
    public String getFrignHystrix() {
        return "這個接口錯了,現在到了這個接口這就是hystrix";
    }

    @Override
    public String getFeign() {
        return "這個接口錯了,現在到了這個接口這就是hystrix";
    }
}

在FeignController添加api接口

 

測試:你先訪問http://localhost:8006/feignHystrix  然後再把客戶端1斷開,你在訪問自己可以試試兩次結果

8.網關

zuul和getway的區別和選擇

Spring Cloud Gateway 是 Spring Cloud 微服務平臺的一個子項目,屬於 Spring 開源社區,依賴名叫:spring-cloud-starter-gateway。它是 Spring Cloud 的一個全新項目,該項目是基於 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,它旨在爲微服務架構提供一種簡單有效的統一的 API 路由管理方式。Spring Cloud Gateway 作爲 Spring Cloud 生態系統中的網關,目標是替代 Netflix Zuul,其不僅提供統一的路由方式,並且基於 Filter 鏈的方式提供了網關基本的功能,例如:安全,監控/指標,和限流。

Spring Cloud Gateway 的特徵:

  • 基於 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 動態路由
  • Predicates 和 Filters 作用於特定路由
  • 集成 Hystrix 斷路器
  • 集成 Spring Cloud DiscoveryClient
  • 易於編寫的 Predicates 和 Filters
  • 限流
  • 路徑重寫

 

Zuul 是 Netflix 公司的開源項目,Spring Cloud 在 Netflix 項目中也已經集成了 Zuul,依賴名叫:spring-cloud-starter-netflix-zuul。它提供了一個框架,可以對過濾器進行動態的加載,編譯,運行。過濾器之間沒有直接的相互通信。他們是通過一個RequestContext的靜態類來進行數據傳遞的。RequestContext類中有ThreadLocal變量來記錄每個Request所需要傳遞的數據。過濾器是由Groovy寫成。這些過濾器文件被放在Zuul Server上的特定目錄下面。Zuul會定期輪詢這些目錄。修改過的過濾器會動態的加載到Zuul Server中以便於request使用。

Zuul可以通過加載動態過濾機制,從而實現以下各項功能:

  • 驗證與安全保障: 識別面向各類資源的驗證要求並拒絕那些與要求不符的請求。
  • 審查與監控: 在邊緣位置追蹤有意義數據及統計結果,從而爲我們帶來準確的生產狀態結論。
  • 動態路由: 以動態方式根據需要將請求路由至不同後端集羣處。
  • 壓力測試: 逐漸增加指向集羣的負載流量,從而計算性能水平。
  • 負載分配: 爲每一種負載類型分配對應容量,並棄用超出限定值的請求。
  • 靜態響應處理: 在邊緣位置直接建立部分響應,從而避免其流入內部集羣。
  • 多區域彈性: 跨越AWS區域進行請求路由,旨在實現ELB使用多樣化並保證邊緣位置與使用者儘可能接近。



作者:一個會寫詩的程序員
鏈接:https://www.jianshu.com/p/e0434a421c03
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

 

 

 

一、Zuul(俗稱springcloud的看門狗)

1.新建一個springboot2.0x的空架子,在pom中引入

<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>
   <version>2.1.2.RELEASE</version>
</dependency>


--------------------------------------------------------

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

2.再啓動類加入註解

@EnableZuulProxy
@EnableEurekaClient

 3.配置yml文件

server:
  port: 8017
eureka:
  client:
    serviceUrl:
      defaultZone: http://herbert:[email protected]:8010/eureka/
spring:
  application:
    name: eureka-zuul
zuul:
  routes:
    api-a:
      path: /api-one/**
      serviceId: CLIENT-STUDENT-ONE
    api-b:
      path: /api-two/**
      serviceId: CLIENT-STUDENT-TWO

4.現在基本的zuul就搭建起來了。把項目跑起來訪問client1的feign接口

原來訪問是:localhost:8005/feign

現在通過zuul訪問:localhost:8017/api-one/feign 就可以了

5.寫zuulFilter

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author:hemingzhu
 * @date: 2019/11/23 10:27
 * @Explanation:
 */
@Component
public class ZuulFiterTest extends ZuulFilter {

    @Override
    public String filterType() {
        System.out.println("11111");
        return "pre"; // 可以在請求被路由之前調用
    }

    @Override
    public int filterOrder() {
        // filter執行順序,通過數字指定 ,優先級爲0,數字越大,優先級越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        // 是否執行該過濾器,此處爲true,說明需要過濾
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(("--->>> TokenFilter {},{}"+ request.getMethod()+"->"+request.getRequestURL().toString()));
        String token = request.getParameter("token");// 獲取請求的參數
        if (StringUtils.isNotBlank(token)) {
            ctx.setSendZuulResponse(true); //對請求進行路由
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);
            return null;
        } else {
            ctx.setSendZuulResponse(false); //不對其進行路由
            ctx.setResponseStatusCode(400);
            ctx.setResponseBody("token is empty");
            ctx.set("isSuccess", false);
            return null;
        }
    }
}

過濾器這就成功了

6.回退機制fallback

package com.herbert.eureak.zuul.fallback;


import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;



/**
 * @Author:hemingzhu
 * @date: 2019/11/23 10:54
 * @Explanation:
 */
@Component
public class ZuulFallBack implements FallbackProvider {

    @Override
    public String getRoute() {
        return null;  //服務id,可以用* 或者 null 代表所有服務都過濾
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK; //請求網關成功了,所以是ok
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("錯誤".getBytes("UTF-8")); //返回前端的內容
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); //設置頭
                return httpHeaders;
            }
        };


    }
}

測試:我們將客戶端掛了訪問  ----》 localhost:8017/api-one/feign?token=1  (token主要是過filter的,如果不寫將filter屏蔽了就好)

zuul我們就說到這裏

二、getway

 

 

 

 

 

---------------------------------------------------後續慢慢更新------------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章