springcloud項目整體搭建過程文檔說明

簡單的springcloud(採用的版本爲:Finchley.RELEASE  springboot版本爲:2.0.3.RELEASE):
    1.創建註冊中心Eureka-server  
        1.1:需要的pom座標:
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        1.2:在啓動類上加註解:
            @EnableEurekaServer :標識是一個註冊中心
        1.3:添加配置文件  application.yml/application.properties
            server:
              port: 8761 #註冊中心端口號

            eureka:
              instance:
                hostname: localhost
              client:
                #聲明自己是一個服務
                registerWithEureka: false
                fetchRegistry: false
                serviceUrl: #註冊中心地址
                  defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
        注:註冊中心完成
    2.創建客戶端(消費者,一個簡單的客戶端):
        2.1:需要的pom座標:
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        2.2:啓動類添加註解:
            @EnableEurekaClient (注:這個註解可加可不加不影響) 聲明這是一個客戶端(消費着)
        2.3:修改配置文件:
            server:
              port: 8771 #客戶端的端口號
            eureka:
              client:
                service-url:
                  defaultZone: http://localhost:8761/eureka/ #指定註冊中心的地址
            spring:
              application:
                name: product-client #客戶端的名稱,必選項,註冊中心需要用到,註冊中心使用的就是此名稱

    3.客戶端間的調用:
        3.1:選擇feign和ribbon feign中已經集成好了ribbon.  所以選擇feign
            3.1.1:導入feign對應的pom座標
                    <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-openfeign</artifactId>
                    </dependency>
            3.1.2:如果是ribbon的話,對應的pom座標
                     <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                    </dependency>
                3.1.2.1:還需要在啓動類中注入一個Bean,用於調用其他服務並開啓負載均衡策略
                    @Bean
                    @LoadBalanced
                    public RestTemplate restTemplate(){
                        return new RestTemplate();
                    }
                3.1.2.2:調用方式:
                    a.注入RestTemplate類。
                    b.使用RestTemplate調用對應的方法。
                注:底層可查看@LoadBalanced。實際使用的是LoadBalancerClient這個類。內部通過這個去註冊中心查找到對應的服務的所有節點,然後根據對應的負載均衡策略進行選擇節點。然後返回給最外層,也就是選擇好某個節點後進行調用,默認的負載均衡策略是輪詢策略。可以配置負載均衡策略。配置完成後使用feign同樣生效
                    #自定義負載均衡策略
                    product-client: #服務名稱
                      ribbon:
                        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  隨機策略可查看IRule類的子類。
                注:ribbon的默認超時時間爲: 60秒
                    設置ribbon的超時和重試設置
                    ribbon:
                      ReadTimeout: 3000
                      ConnectTimeout: 3000    
                      MaxAutoRetries: 1 #同一臺實例最大重試次數,不包括首次調用
                      MaxAutoRetriesNextServer: 1 #重試負載均衡其他的實例最大重試次數,不包括首次調用
                      OkToRetryOnAllOperations: false  #是否所有操作都重試  慎用
                    根據上面的參數計算重試的次數:MaxAutoRetries+MaxAutoRetriesNextServer+(MaxAutoRetries *MaxAutoRetriesNextServer) 即重試3次 則一共產生4次調用 
                    如果在重試期間,時間超過了hystrix的超時時間,便會立即執行熔斷,fallback。所以要根據上面配置的參數計算hystrix的超時時間,使得在重試期間不能達到hystrix的超時時間,不然重試機制就會沒有意義 
                    
                    hystrix超時時間的計算: (1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout 即按照以上的配置 hystrix的超時時間應該配置爲 (1+1+1)*3=9秒

                    Hystrix的超時計算規則應該是 Hystrix的超時時間=Ribbon的重試次數(包含首次)*(ribbon.ReadTimeout+ribbon.ConnectTimeout),如果以你的配置爲例Hystrix的超時配置應該是=4*(3000+3000)=24000,即24秒。

                    當ribbon超時後且hystrix沒有超時,便會採取重試機制。當OkToRetryOnAllOperations設置爲false時,只會對get請求進行重試。如果設置爲true,便會對所有的請求進行重試,如果是put或post等寫操作,如果服務器接口沒做冪等性,會產生不好的結果,所以OkToRetryOnAllOperations慎用。

                    如果不配置ribbon的重試次數,默認會重試一次 
                    注意: 
                    默認情況下,GET方式請求無論是連接異常還是讀取異常,都會進行重試 
                    非GET方式請求,只有連接異常時,纔會進行重試


            3.1.3:使用feign調用接口(基於接口實現feign);
                a.創建一個接口類,在接口類上加註解@FeignClient然後值有name 和 fallback   name:是需要調用的服務的名稱
                                                                                         fallback:失敗的回調(熔斷處理,相當於家裏的用電,當用電到達某一閾值,電路就會自動跳閘,從而保護整個電路。),失敗的一個降級處理。寫的是一個類。每一個方法對應一個方法,此方法參數類型和返回值必須和接口的一樣。如果使用feign調用的接口失敗了,則會進入這個方法,可以在內部進行一些操作並且返回一些虛擬數據,保證後續服務不會崩潰(解決雪崩效應)。
                b.使用feign調用接口的時候,如果有參數 基本類型傳遞使用@RequestParm   如果是對象的話,要使用@RequestBody傳遞。
                注:使用Feign調用接口分兩層,ribbon的調用和hystrix的調用,所以ribbon的超時時間和Hystrix的超時時間的結合就是Feign的超時時間。一般情況下都是ribbon的超時時間(<)hystrix的超時時間(因爲涉及到ribbon的重試機制因爲ribbon的重試機制和Feign的重試機制有衝突,所以源碼中默認關閉Feign的重試機制。
                hystrix的默認超時時間是一秒,配置了hystrix的超時時間必須還要配置ribbon的超時時間,否則會有問題。
                在使用 Ribbon 時,只需要配置 Hystrix 的超時時間就可以生效,不需要額外配置 Ribbon 的超時時間

                記錄一個異常,就是第一次啓動完成後,調用服務的時候總是在第一次出現超時的情況。這是因爲懶加載的特性,在第一次用到的時候纔去加載一些東西。而加載這些東西需要耗時,可能耗時的時候就已經出發了熔斷/降級處理。
                解決辦法有兩種   1.設置超時時間:全局設置超時時間爲60秒
                                                 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
                                                 # 設置ribbon超時時間
                                                 ribbon:
                                                   ReadTimeout: 20000
                                                   ConnectTimeout: 20000
                                 2. 配置立即加載。不過還需要配置所有的客戶端服務
                                                 ribbon:
                                                    eager-load:
                                                        enabled: true
                                                        clients: distribution, material-product, outer-data  #客戶端服務


        3.2:引入Hystrix(斷路器,熔斷)
            a.引入所需要的pom座標文件
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
                </dependency>
            b.啓動類開啓斷路器,加註解//@EnableHystrix
                                        @EnableCircuitBreaker   這兩個都可以,上邊的註解裏包含了下邊的註解。標識啓用斷路器功能。
            c.配置文件配置斷路器。需要配置表示feign開啓hystrix  和  hystrix的超時時間配置。hystrix的默認超時時間時1秒。
                feign:
                #開啓斷路器
                  hystrix:
                    enabled: true
                #修改調用超時時間
                  client:
                    config:
                      default:
                        connectTimeout: 3000
                        readTimeout: 2000

                #修改hystrix的調用超時時間配置
                hystrix:
                  command:
                    default:
                      execution:
                        isolation:
                          thread:
                            timeoutInMilliseconds: 4000
            d.使用:
                1. 在方法上加註解@HystrixCommand key有fallbackMethod  表示出現異常時要熔斷的方法。
                    ps:訪問該接口時報錯了或者超時了,會進入fallbackMethod設置的對應的方法內部。進行一些記錄操作返回一些給用戶的提示等操作。
            注:1.feign/ribbon的超時時間一定要大於hystrix的超時時間,因爲只要訪問到接口,feign/ribbon 和 hystrix 的計時器就會同步啓動,去計算。如果沒有到達feign/ribbon的超時時間,但是到達了hystrix的超時時間,儘管沒有報錯,但是還是會進入的hystrix的熔斷方法。  
                2.設置的fallbackMethod的方法的請求參數和返回結果要和@HystrixCommand標記的接口的一致,否則會出問題。
                

        3.3:引入hystrix儀表盤 hystrix-dashboard。一個健康檢查。
            hystrix dashboard 儀表盤解釋:健康檢查監控hystrix的各項指標信息,檢查接口調用的成功與失敗記錄等信息,如果失敗率超過50%,會開啓熔斷,後續請求將不會請求接口。
            a:引入pom文件:
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
                </dependency>
                <!-- 此依賴是打開 Actuator 作用 -->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-actuator</artifactId>
                </dependency>
            b.啓動類加註解:
                @EnableHystrixDashboard
            c.配置文件增加endpoint,開啓所有訪問權限,放行了所有端點,(這樣貌似不安全,默認 Actuator 只暴露了2個端點,heath 和 info)
                management:
                  endpoints:
                    web:
                      exposure:
                        include: "*"
                注:這個是用來暴露 Actuator 的所有端點的,這一點很重要,不配置你的 Hystrix Dashboard 會出現 Unable to connect to Command Metric Stream 的問題
            d.訪問入口
                http://localhost:8781/hystrix

                Hystrix Dashboard輸入: http://localhost:8781/actuator/hystrix.stream 

        3.4:引入鏈路追蹤:seluth,其主要作用是做一個日誌的埋點,出現錯誤時可以根據日誌的埋點id找到對應的信息/報錯位置。Sleuth可以與日誌框架Logback、SLF4J輕鬆地集成,
            a.引入pom文件
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-sleuth</artifactId>
                </dependency>
            b.配置文件:
                spring:
                  #配置採樣百分比,開發環境可以設置爲1,表示全部,生產就用默認(比如請求100次我記錄百分之多少/多少次。1代表全部,根據實際情況調節)
                  sleuth:
                    sampler:
                      probability: 1
            b. 集成可直接使用,但是需要加log否則控制檯不會輸出日誌,本示例使用的是log4j
                private final Logger log = LoggerFactory.getLogger(getClass());
                log.info("查詢商品");
            c.輸出的格式
2020-03-26 16:32:08.117  INFO [product-client,1371c3a83b9b13a5,6ac4a8cc3fbbfa12,true] 1812 --- [nio-8772-exec-2] t.o.p.controller.ProductController: findProductById
2020-03-26 16:32:08.117  INFO [product-client,1371c3a83b9b13a5,6ac4a8cc3fbbfa12,true] 1812 --- [nio-8772-exec-2] t.o.product.service.ProductServiceImpl: 查詢商品
                解釋:[]中第一個標識服務的名稱,第二個標識本次請求的id唯一標識(一個請求分配的ID號,用來標識一條請求鏈路。),第三個標識一個工作的基本單元,一個請求可以又多個步驟,而第三個標識每一個步驟。第四個表示  是否要將該信息輸出到類似Zipkin這樣的聚合器進行收集和展示。


        3.5:引入zipkin,上邊所提到的聚合器,這裏用於手機每次請求鏈路追蹤所產生的記錄,都在該組件內存在。
            a.引入pom文件:
                <!--其中已經包含了鏈路追蹤seluth-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-zipkin</artifactId>
                </dependency>
            b.配置文件:
                spring:
                  #zipkin服務所在地址
                  zipkin:
                    base-url: http://www.oyygke.top:9411/ #該地址表示zipkin所在地址
            c.使用:
                集成好sleuth和zipkin之後,進行發送請求,然後訪問上邊配置的zipkin的地址,就會看到請求記錄。點擊可查看詳情--整個請求的鏈路是怎麼走的。

        3.6:引入網關zuul
            a.引入pom文件
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
                </dependency>
            b.添加註解,開啓網關
                @EnableZuulProxy
               c.作用
                   使用網關進行過濾和請求轉發的作用,經過網關轉發到某服務。
               d.配置文件
                   zuul:
                  routes:
                    #相當於oyygke映射到order-client
                    order-client: /oyygke/order/**
                    product-client: /oyygke/product/**
                  #忽略product-client,不經過網關
                #  ignored-services: product-client
                  #只使用一種方式進行訪問,過濾以client結尾的服務
                  ignored-patterns: /*-client/**
                  #處理http請求頭爲空的問題
                  sensitive-headers:
                ribbon: #添加請求超時設置,如果不配置,默認第一次訪問會進入到熔斷的超時處理機制。因爲可能還沒有加載到,第一次加載需要時間,所以需要添加超時時間設置。
                  ReadTimeout: 6000
                  ConnectTimeout: 6000
            e.使用過濾
                i.新建類繼承ZuulFilter,實現其中的方法。相當於一個配置類,記得添加@component。還可以進行限流處理,
                    //令牌桶  每秒產生多少個令牌   這個需要進行壓測確定可以有多少個令牌
                    //令牌需要配置到配置文件中更改   多少個網管就是  總數/網關數量
                    //guava谷歌的框架 限流
                    private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
                工具類:HttpStatus.TOO_MANY_REQUESTS.value()  //表示請求過多。
                示例:過濾token,表示   如果訪問該接口沒有token則過濾掉直接返回對應的錯誤提示信息。
                @Component
                public class LoginFilter extends ZuulFilter {
                    /**
                     * 過濾器的類型   前置還是後置
                     * @return
                     */
                    @Override
                    public String filterType() {
                        return PRE_TYPE; //表示請求接口前執行
                    }
                    /**
                     * 過濾器的一個級別  越小越先執行
                     * @return
                     */
                    @Override
                    public int filterOrder() {
                        return 4;
                    }
                    /**
                     * 是否進行過濾
                     * @return
                     */
                    @Override
                    public boolean shouldFilter() {
                        //全局的上下文對象
                        RequestContext context = RequestContext.getCurrentContext();
                        HttpServletRequest request = context.getRequest();
                        //如果請求路徑包含order,則需要進行過濾驗證
                        if(request.getRequestURI().contains("/order/")){
                            return true;
                        }
                        return false;
                    }
                    /**
                     * 業務邏輯
                     * @return
                     * @throws ZuulException
                     */
                    @Override
                    public Object run() throws ZuulException {
                        RequestContext context = RequestContext.getCurrentContext();
                        HttpServletRequest request = context.getRequest();

                        String token = request.getHeader("token");
                        if(StringUtils.isBlank(token)){
                            token = request.getParameter("token");
                        }
                        if(StringUtils.isBlank(token)){
                            context.setSendZuulResponse(false);
                            context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
                        }
                        return null;
                    }
                }


        3.7:配置中心  config-server/config-client
            a.先搭建配置中心服務,config-server    配置中心可以使用   git、碼雲等 
            b.product-client-dev.yml  配置中心的文件名採用  服務名-後綴命名。dev/test等
            c.pom文件引入:
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-config-server</artifactId>
                </dependency>
            d.@EnableConfigServer  表示這是一個配置服務中心
            e.配置文件
                spring:
                  application:
                    name: config-server  #服務名稱
                  cloud:
                    config:
                      server:
                        git:
                          uri: https://gitee.com/xc-rong/spring-cloud.git  #碼雲的項目地址
                          username: xxx  #碼雲賬號
                          password: xxx #碼雲密碼
                          timeout: 5
                          default-label: master #使用哪個分支的
            f.修改原有服務爲配置中心的客戶端  config-client
                i.引入pom文件
                    <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-config-client</artifactId>
                    </dependency>
                ii.修改原有的application.yml爲bootstrap.yml /bootstrap.properties
                iii.修改配置文件
                    spring:
                      application:
                        name: order-client #服務名稱
                      cloud:
                        config:
                          discovery:
                            enabled: true #開啓通過服務訪問config-server的功能
                            service-id: CONFIG-SERVER #配置中心的服務名
                          #後綴 一個區分  指定環境
                          profile: dev
                          #分支的區分,指定分支
                          label: master
                iiii. 將一些配置文件的內容放到填寫的碼雲/git倉庫上。項目啓動的時候會從倉庫拉去配置文件。
                注:到此配置完成,可以啓動項目進行查看日誌
            g.配置消息總線,用於動態拉取配置,(表示 在碼雲/git倉庫更改配置文件之後,動態拉取不需要重啓項目,但是線下可以這樣,線上的話不建議這樣,因爲沒辦法觀察是否拉取到了最新的配置文件)
                i:引入pom文件
                    <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
                    </dependency>
                ii.配置文件添加mq
                    spring:
                      application:
                        name: product-client
                      rabbitmq:
                        host: www.oyygke.top
                        port: 5672
                        username: guest
                        password: guest
                ii.添加註解,在需要動態更新配置的地方添加註解 @RefreshScope
                iii.至此代碼中的內容添加完畢。動態更新的話需要手動的訪問一個地址進行拉取最新配置
                    http://localhost:2009/refresh    #表示每個服務的ip+端口號+refresh 進行刷新,每次只刷新一個服務,多個服務需要調用多次,而且該接口只支持post請求,get請求不支持。

                   注:必須要有這個pom
                       <!--開啓監控功能-->
                    <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-actuator</artifactId>
                    </dependency>
        4.完成以後可能會出現的小問題。
            註冊中心每個服務的地址可能不是ip+端口號  可能是一串字母+端口號  這樣放到線上是有問題的,需要在配置文件中在加下配置,使註冊中心的地址是ip+端口號
            解決辦法:
                eureka:
                  client:
                    service-url:
                      defaultZone: http://localhost:8761/eureka/
                  instance:
                    instance-id: ${spring.cloud.client.ip-address}:${server.port} #表示每個服務的ip示自定義id,ip+端口號格式
                    prefer-ip-address: true #將IP註冊到Eureka Server上

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