分類
發燒車訊

說說TCP的三次握手和四次揮手

一、傳輸控制協議TCP簡介

1.1 簡介

TCP(Transmission Control Protocol) 傳輸控制協議,是一種 面向連接的、可靠的、基於字節流的傳輸層 通信協議。

TCP是一種面向連接(連接導向)的、可靠的基於字節流的傳輸層通信協議。TCP將用戶數據打包成報文段,它發送后啟動一個定時器,另一端收到的數據進行確認、對失序的數據重新排序、丟棄重複數據。

TCP把連接作為最基本的對象,每一條TCP連接都有兩個端點,這種端點我們叫作套接字(socket),將端口號拼接到IP地址即構成了套接字,例如 192.1.1.6:50030

1.2 特點

  • 面向連接的、可靠的、基於字節流的 傳輸層 通信協議
  • 將應用層的數據流分割成文段併發送給目標節點的TCP層
  • 數據包都有序號,對方收到則發送ACK確認,未收到則重傳
  • 使用校驗和來檢驗數據在傳輸過程中是否有誤

二、TCP報文頭

1、源端口(Source Port)/ 目的端口(Destination Port):他們各佔2個字節,標示該段報文來自哪裡(源端口)以及要傳給哪個上層協議或應用程序(目的端口)。進行tcp通信時,一般client是通過系統自動選擇的臨時端口號,而服務器一般是使用知名服務端口號或者自己指定的端口號(比如DNS協議對應端口53,HTTP協議對應80)

2、序號(Sequence Number):佔據四個字節,TCP是面向字節流的,TCP連接中傳送的字節流中的每個字節都按順序編號,例如如一段報文的序號字段值是107,而攜帶的數據共有100個字段,如果有下一個報文過來,那麼序號就從207(100+107)開始,整個要傳送的字節流的起始序號必須要在連接建立時設置。首部中的序號字段值指的是本報文段所發送的數據的第一個字節的序號

3、確認序號(Acknowledgment Number):4個字節,是期望收到對方下一個報文段的第一個數據字節的序號,若確認號=N,則表明:到序號N-1為止的所有數據都已正確收到,例如:B收到A發送過來的報文,其序列號字段是301,而數據長度是200字節,這表明了B正確的收到了A到序號500(301+200-1)為止的數據,因此B希望收到A的下一個數據序號是501,於是B在發送給A的確認報文段中,會把ACK確認號設置為501

4、數據偏移(Offset):4個字節。指出TCP報文段的數據起始處距離報文段的起始處有多遠,這個字段實際上是指出TCP報文段的首部長度。由於首部中還有長度不確定的選項字段,因此數據偏移字段是必要的。單位是32位字,也就是4字節,4位二進制最大表示15,所以數據偏移也就是TCP首部最大60字節

5、保留(Reserved):6個字節。保留域

6、TCP Flags:控制位,由八個標誌位組成,每個標誌位表示控制的功能,我們主要來介紹TCP Flags中常用的六個,

  • URG(緊急指針標誌):當URG=1時,表明緊急指針字段有效。它告訴系統此報文段中有緊急數據,應儘快傳送(相當於高優先級的數據),而不要按原來的排隊順序來傳送。例如,已經發送了很長的一個程序在主機上運行。但後來發現了一些問題,需要取消該程序的運行。因此用戶從鍵盤發出中斷命令。如果不使用緊急數據,那麼這兩個字符將存儲在接收TCP的緩存末尾。只有在所有的數據被處理完畢后這兩個字符才被交付接收方的應用進程。這樣做就浪費了許多時間

  • ACK(確認序號標誌):當ACK=1時確認號字段有效。當ACK=0時,確認號無效。TCP規定,在連接建立后所有的傳送的報文段都必須把ACK置1

  • PSH(push標誌):當兩個應用進程進行交互式的通信時,有時在一端的應用進程希望在鍵入一個命令后立即就能收到對方的響應。在這種情況下,TCP就可以使用推送操作。這時,發送方TCP把PSH置1,並立即創建一個報文段發送出去。接收方TCP收到PSH=1的報文段,就儘快地交付接收應用進程,而不再等到整個緩存都填滿了後向上交付

  • RST(重置連接標誌):TCP連接中出現嚴重差錯(如由於主機崩潰或其他原因),必須釋放連接,然後再重新建立運輸連接,可以用來拒絕一個非法的報文段或拒絕打開一個連接

  • SYN(同步序號,用於建立連接過程):在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文段。對方若同意建立連接,則應在相應的報文段中使用SYN=1和ACK=1。因此,SYN置為1就表示這是一個連接請求或連接接受保溫。

  • FIN(finish標誌,用於釋放連接):當FIN=1時,表明此報文段的發送方的數據已發送完畢,並要求釋放運輸連接

7、窗口(Window)是TCP流量控制的一個手段。這裏說的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告訴對方本端的TCP接收緩衝區還能容納多少字節的數據,這樣就可以控制發送數據的速度

8、檢驗和(Checksum):檢驗範圍包括首部和數據兩部分,由發送端填充,接收端對TCP報文段執行CRC算法以檢驗TCP報文段在傳輸過程中是否損壞。這也是TCP可靠傳輸的一個重要保障

9、緊急指針(Urgent Pointer):緊急指針僅在URG=1時才有意義,它指出本報文段中的緊急數據的字節數(緊急數據結束后就是普通數據)。因此,緊急指針指出了緊急數據的末尾在報文段中的位置。當所有緊急數據都處理完時,TCP就告訴應用程序恢復到正常操作。值得注意的是,即使窗口為零時也可發送緊急數據。

10、TCP可選項(TCP Options):長度可變,最長可達40字節。當沒有使用“選項”時,TCP的首部長度是20字節。

三、TCP的三次握手

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。在socket編程中,這一過程由客戶端執行connect來觸發,整個流程如下圖所示:

在TCP/IP協議中,TCP協議提供可靠的連接服務,採用三次握手建立一個連接。

第一次握手: 建立連接時,客戶端發送SYN包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認,SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手: 服務器收到 SYN 包,必須確認客戶的 SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

第三次握手: 客戶端收到服務器的SYN + ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。

3.1 為什麼需要三次握手才能建立連接

  • 為了初始化Sequence Number 的初始值,實現可靠數據傳輸, TCP 協議的通信雙方, 都必須維護一個序列號, 以標識發送出去的數據包中, 哪些是已經被對方收到的。 三次握手的過程即是通信雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟
  • 如果只是兩次握手, 至多只有連接發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認

3.2 首次握手的隱患——SYN超時

一、問題起因分析:
  1. 服務器收到客戶端的SYN,回復SYN和ACK的時候未收到ACK確認
  2. 服務器不斷重試直至超時,Linux默認等待63秒才斷開連接;(重複5次【不包括第一次】,從1秒開始,每次重試都翻倍:1+2+4+8+16+32=63秒)
二、針對SYN Flood的防護措施:
  1. SYN隊列滿后,通過tcp_syncookies參數會發SYN cookie【源端口+目標端口+時間戳組成】
  2. 若為正常連接則Client會回發SYN Cookie,直接建立連接;

3.3 保活機制:

當我們建立連接后,Client出現故障怎麼辦?

  1. 向對方發送保活探測報文,如果未收到響應則繼續發送;
  2. 嘗試次數達到保活探測數仍未收到相應則中斷連接;

四、TCP的四次揮手

所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發,整個流程如下圖所示:

由於TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務后,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

  • 第一次揮手: Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態
  • 第二次揮手: Server收到FIN后,發送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態
  • 第三次揮手: Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態
  • 第四次揮手: Client收到FIN后,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態,完成四次揮手
一、為什麼會有TIME_WAIT狀態

客戶端連接在收到服務器的結束報文段之後,不會直接進入CLOSED狀態,而是轉移到TIME_WAIT狀態。在這個狀態,客戶端連接要等待一段長為2MSL,即兩倍的報文段最大生存時間,才能完全關閉,其原因主要有兩點:

  • 確保有足夠的時間放對方收到ACK包
  • 避免新舊連接混淆
二、為什麼需要四次握手才能斷開連接

因為TCP連接是全雙工的網絡協議,允許同時通信的雙方同時進行數據的收發,同樣也允許收發兩個方向的連接被獨立關閉,以避免client數據發送完畢,向server發送FIN關閉連接,而server還有發送到client的數據沒有發送完畢的情況。所以關閉TCP連接需要進行四次握手,每次關閉一個方向上的連接需要FIN和ACK兩次握手,發送發和接收方都需要FIN報文和ACK報文

三、服務器出現大量CLOSE_WAIT狀態的原因

是由於對方關閉socket連接,我方忙於讀或寫,沒有及時關閉連接

當客戶端因為某種原因先於服務端發出了FIN信號,就會導致服務端被動關閉,若服務端不主動關閉socket發FIN給Client,此時服務端Socket會處於CLOSE_WAIT狀態(而不是LAST_ACK狀態)。通常來說,一個CLOSE_WAIT會維持至少2個小時的時間(系統默認超時時間的是7200秒,也就是2小時)。如果服務端程序因某個原因導致系統造成一堆CLOSE_WAIT消耗資源,那麼通常是等不到釋放那一刻,系統就已崩潰

解決:
1、檢查代碼,特別是釋放資源的代碼
2、檢查配置,特別是處理請求的線程配置

Linux的檢查代碼:netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'

五、總結

到這裏TCP的三次握手四次揮手就講完了,好久都沒有寫技術文章了,寫了一下,感覺還挺好的,上面是博主的認識,有寫的不好的地方,大家可以在評論區討論或者提問,博主看到了會第一時間回復大家,最近也準備開始面試了,先好好準備一下,希望今年可以找到心滿意足的工作,也希望今年面試的小夥伴們都有一個好的office,大家一起加油,我是牧小農,我喂自己帶鹽,大家加油。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

三文搞懂學會Docker容器技術(下)

接着上面一篇:三文搞懂學會Docker容器技術(上)

                         三文搞懂學會Docker容器技術(中)

7,Docker容器目錄掛載

  7.1 簡介

容器目錄掛載:

我們可以在創建容器的時候,將宿主機的目錄與容器內的目錄進行映射,這樣我們就可以實現宿主機和容器目錄的雙向數據自動同步;

  7.2 作用

前面學過cp命令來實現數據傳遞,這種方式比較麻煩;

我們通過容器目錄掛載,能夠輕鬆實現代碼上傳,配置修改,日誌同步等需求;

  7.3 實現

語法:

docker run -it -v  /宿主機目錄:/容器目錄 鏡像名

多目錄掛載

docker run -it -v /宿主機目錄:/容器目錄 -v /宿主機目錄2:/容器目錄2  鏡像名

注意:

如果你同步的是多級目錄,可能會出現權限不足的提示;

這是因為Centos7中的安全模塊selinux把權限禁掉了,我們需要添加  –privileged=true 來解決掛載的目錄沒有權限的問題;

  7.4 掛載目錄只讀

docker run -it -v  /宿主機目錄:/容器目錄:ro 鏡像名

 

8,Docker遷移與備份

  8.1 概述

我們開發的時候,經常自定義鏡像,然後commit提交成鏡像到本地倉庫,但是我們發布到客戶服務器的時候,可以用前面講得搞到hub官方,或者阿里雲,但是有些機密性的項目,是禁止公網存儲的,所以我們只能通過docker鏡像備份和遷移實現;

  8.2 實現

備份鏡像:

docker save -o 備份鏡像的名稱  源鏡像名稱:tag版本

 docker save -o mytomcat7.1.tar java1234/tomcat7:7.1

 

恢復鏡像:

docker load -i 鏡像文件

docker load -i mytomcat7.1.tar

 

9,DockerFile詳解

  9.1 DockerFile簡介

Dockerfile是由一系列命令和參數構成的腳本,這些命令應用於操作系統(centos或者Ubuntu)基礎鏡像並最終創建的一個新鏡像;

我們前面講過的用手工的方式,修改配置文件,或者添加,刪除文件目錄的方式,來構建一種新鏡像;這種手工方式麻煩,容易出錯,而且不能復用;

我們這裏講Dockerfile,用腳本方式來構建自動化,可復用的,高效率的創建鏡像方式,是企業級開發的首選方式;

 

再軟件系統開發生命周期中,採用Dockerfile來構建鏡像;

1、對於開發人員:可以為開發團隊提供一個完全一致的開發環境;

2、對於測試人員:可以直接拿開發時所構建的鏡像或者通過Dockerfile文件構建一個新的鏡像開始工作;

3、對於運維人員:在部署時,可以實現應用的無縫移植。

  9.2 DockerFile常用指令

FROM image_name:tag 定義了使用哪個基礎鏡像啟動構建流程
MAINTAINER user_info 聲明鏡像維護者信息
LABEL key value 鏡像描述元信息(可以寫多條)
ENV key value 設置環境變量(可以寫多條)
RUN command 構建鏡像時需要運行的命令(可以寫多條)
WORKDIR path_dir 設置終端默認登錄進來的工作目錄
EXPOSE port 當前容器對外暴露出的端口
ADD source_dir/file dest_dir/file 將宿主機的文件複製到容器內,如果是一個壓縮文件,將會在複製后自動解壓
COPY source_dir/file dest_dir/file 和ADD相似,但是如果有壓縮文件是不能解壓
VOLUME 創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等
CMD 指定容器啟動時要運行的命令,假如有多個CMD,最後一個生效
ENTRYPOINT 指定容器啟動時要運行的命令
ONBUILD 當構建一個被繼承的Dockerfile時運行的命令,父鏡像在被子鏡像繼承後父鏡像的onbuild被觸發。可以把ONBUID理解為一個觸發器。

 

10,Docker私有倉庫

  10.1 簡介

Docker私有倉庫主要是企業內部用來存放鏡像的倉庫,相對官方倉庫以及阿里雲倉庫,具有更高的保密安全級別;

  10.2 私有倉庫搭建

第一步:拉取私有倉庫鏡像 (私有倉庫程序本身就是一個鏡像)

docker pull registry

第二步:啟動私有倉庫容器

docker run -di –name=myRegistry -p 5000:5000 registry

第三步:測試

http://192.168.1.112:5000/v2/_catalog

看到這個 說明啟動OK。因為倉庫里還沒有鏡像,所以就是空的;

第四步:etc/docker 修改daemon.json,讓docker信任私有倉庫地址

“insecure-registries”: [“192.168.1.112:5000”]

 

第五步:修改配置后重啟docker;

 systemctl restart docker

  10.3 私有倉庫測試

第一步:標記此鏡像為私有倉庫的鏡像

docker tag tomcat:7 192.168.1.112:5000/mytomcat7

第二步:上傳鏡像到私有倉庫

docker push 192.168.1.112:5000/mytomcat7

此時私有倉庫里已經有了這個鏡像;

第三步:刪除192.168.1.112:5000/mytomcat7本地倉庫鏡像

docker rmi -f 192.168.1.112:5000/mytomcat7

第四步:從私有倉庫拉取192.168.1.112:5000/mytomcat7鏡像,並運行;

docker run -it -p 8080:8080 192.168.1.112:5000/mytomcat7

第五步:瀏覽器運行 http://192.168.1.112:8080測試

 

——————————————————————————————————————————

作者: java1234_小鋒

出處:https://www.cnblogs.com/java688/p/13174647.html

版權:本站使用「CC BY 4.0」創作共享協議,轉載請在文章明顯位置註明作者及出處。

——————————————————————————————————————————

 

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

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

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

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

分類
發燒車訊

快速打造屬於你的接口自動化測試框架

1 接口測試

接口測試是對系統或組件之間的接口進行測試,主要是校驗數據的交換,傳遞和控制管理過程,以及相互邏輯依賴關係。
接口自動化相對於UI自動化來說,屬於更底層的測試,這樣帶來的好處就是測試收益更大,且維護成本相對來說較低,是我們進行自動化測試的首選

2 框架選型

目前接口自動化的框架比較多,比如jmeter,就可以集接口自動化和性能測試於一體,該工具編寫用例效率不高;還有我們常用的postman,結合newman也可以實現接口自動化;Python+unittest+requests+HTMLTestRunner 是目前比較主流的測試框架,對python有一定的編碼要求;
本期我們選擇robotframework(文中後續統一簡稱為RF)這一個比較老牌的測試框架進行介紹,RF是一個完全基於 關鍵字 測試驅動的框架,它即能夠基於它的一定規則,導入你需要的測試庫(例如:其集成了selenium的測試庫,即可以理解為操作控件的測試底層庫),然後基於這些測試庫,你能應用TXT形式編寫自己的關鍵字(支持python和java語言,這些關鍵字即你的庫組成),之後,再編寫(測試用例由測試關鍵字組成)進行測試;他支持移動端、UI自動化和接口自動化的測試

3 環境搭建

  • python的安裝:目前選取的python3以上的版本,RF的運行依賴python
  • robotframework:參考https://www.jianshu.com/p/9dcb4242b8f2
  • jenkins:用於調度RF的用例執行環境
  • gitlab:代碼倉庫

4 需求

4.1 需求內容
接口內容:實現一個下單,並檢查訂單狀態是否正常的場景;該需求涉及到如下三個接口

  • 下單接口
  • 訂單結果查詢接口
  • 下單必須帶上認證標識,生成token的接口

環境覆蓋:需要支持能在多套環境運行,比如測試和預發布環境
系統集成:需要能夠集成在CICD中,實現版本更新后的自動檢測

4.2 用例設計
4.2.1 用例設計,根據業務場景設計測試用例,方便後續實現

4.2.2 測試數據構造,預置不同環境的測試數據,供實現調用

5 整體實現架構

接口測試實現層:在RF,通過引用默認關鍵字 RequestsLibrary (實現http請求)和通過python自定義關鍵字來完成用例實現的需求;
jenkins調度:在jenkins上配置一個job,設置好RF用例執行的服務器和發送給服務器相關的RF執行的指令,並且在jenkins中配置好測試報告模板,這樣用例便可以通過jenkins完成執行併發送測試結果給項目干係人;
生成用例執行的API:上圖中藍色部分,就是為了將jenkins的job生成一個可訪問api接口,方便被測項目的CICD集成;
集成到被測系統CICD流程:將上面步驟中封裝的API配置在被測應用的__gitlab-ci.yml__中,完成整個接口自動化的閉環

6 RF用例實現

6.1 引用的內置關鍵字

  • RequestsLibrary 構造http的請求,get|post等請求
getRequests
# get請求的入參
    [Arguments]    ${url_domain}    ${getbody}    ${geturl}    ${getToken}
    Create session    postmain    ${url_domain}
# 定義header的內容
    ${head}    createdictionary    content-type=application/json    Authorization=${getToken}    MerchantId=${s_merchant_id}
# get請求
    ${addr}    getRequest    postmain    ${geturl}    params=${getbody}    headers=${head}
# 請求狀態碼斷言
    Should Be Equal As Strings    ${addr.status_code}    200
    ${response_get_data}    To Json    ${addr.content}
# 返回http_get請求結果
    Set Test Variable    ${response_get_data}	 
    Delete All Sessions

6.2 自定義關鍵字

  • getEnvDomain 用於從自定義的configs.ini文件獲取對應環境的微服務的請求域名
    configs.ini的內容
# 獲取configs.ini的內容
import configparser
def getEnv(path,env):
    config = configparser.ConfigParser()
    config.read(path)
    passport = config[env]['passport']
    stock=config[env]['stock']
    finance=config[env]['finance']
    SUP = config[env]['SUP']
    publicApi = config[env]['publicApi']
    publicOrder = config[env]['publicOrder']
    data_dict={'passport':passport,'stock':stock,'finance':finance,'SUP':SUP,'publicApi':publicApi,'publicOrder':publicOrder}
    return data_dict
  • excelTodict 用戶將excel中的內容作為字典返回
import xlrd

'''
通用獲取excel數據
@:param path excel文件路徑
@:param sheet_name excel文件裏面sheet的名稱 如:Sheet1
@:env 環境,是IT還是PRE
'''
def getExcelDate(path, sheet_name,env):
    bk = xlrd.open_workbook(path)
    sh = bk.sheet_by_name(sheet_name)
    row_num = sh.nrows
    data_list = []
    for i in range(1, row_num):
        row_data = sh.row_values(i)
        data = {}
        for index, key in enumerate(sh.row_values(0)):
            data[key] = row_data[index]
        data_list.append(data)
    data_list1 = []
    for x in data_list:
        #print('這是'+str(x))
        if(x.get('env')==env):
            data_list1.append(x)
    return data_list1
  • getToken 提供接口下單的授權token
*** Keywords ***
# 根據傳入的clientid、secret生成對應的token
getToken
    [Arguments]    ${client_id}    ${client_secret}    ${url_domain}
    Create session    postmain    ${url_domain}
    ${auth}    createdictionary    grant_type=client_credentials    client_id=${client_id}    client_secret=${client_secret}
    ${header}    createdictionary    content-type=application/x-www-form-urlencoded
    ${addr}    postRequest    postmain    /oauth/token    data=${auth}    headers=${header}
    Should Be Equal As Strings    ${addr.status_code}    200
    ${responsedata}    To Json    ${addr.content}
    ${access}    Get From Dictionary    ${responsedata}    access_token
    ${token}    set variable    bearer ${access}
    Set Test Variable    ${token}
    Delete All Sessions
  • getAllDate 獲取該用例下的所有數據
getAllData
    [Arguments]    ${row_no}
    getEnvDomain
    getBalance    ${row_no}
    getStockNum    ${row_no}
    getSupProPrice    ${row_no}
    getProPrice    ${row_no}
    Set Test Variable    ${publicOrderUrl}
    Set Test Variable    ${FPbalance}
    Set Test Variable    ${Pbalance}
    Set Test Variable    ${Sbalance}
    Set Test Variable    ${Jbalance}
    Set Test Variable    ${Cardnum}
    Set Test Variable    ${sprice}
    Set Test Variable    ${price}
    Set Test Variable    ${j_merchant_id}
    Set Test Variable    ${s_merchant_id}
    Set Test Variable    ${stock_id}
    Set Test Variable    ${p_product_id}
    Set Test Variable    ${s_product_id}

  • 實現demo
*** Settings ***
Test Template
Resource          引用所有資源.txt

*** Test Cases ***
*** Settings ***
Test Template
Resource          引用所有資源.txt

*** Test Cases ***
01 下單卡密直儲商品
    [Tags]    order
    LOG    ---------------------獲取下單前的數量、餘額------------------------------------------
    getAllData    0
    ${Cardnum1}    set variable    ${Cardnum}
    ${FPbalance1}    set variable    ${FPbalance}
    ${Pbalance1}    set variable    ${Pbalance}
    ${Sbalance1}    set variable    ${Sbalance}
    ${Jbalance1}    set variable    ${Jbalance}
    ${CustomerOrderNo1}    Evaluate    random.randint(1000000, 9999999)    random
    ${Time}    Get Time
    log    ------------------------下單操作-------------------------------------------------------
    getToken    100xxxx    295dab07a9xxxx9780be0eb95xxxx   ${casUrl}
    ${input_cs}    create dictionary    memberId=${j_merchant_id}    clientId=1xxx079    userId=string    shopType=string    customerOrderNo=${CustomerOrderNo1}
    ...    productId=${p_product_id}    buyNum=1    chargeAccount=otest888888    notifyUrl=string    chargeIp=string    chargePassword=string
    ...    chargeGameName=string    chargeGameRole=string    chargeGameRegion=string    chargeGameSrv=string    chargeType=string    remainingNumber=0
    ...    contactTel=string    contactQQ=string    customerPrice=0    poundage=0    batchNumber=    originalOrderId=string
    ...    shopName=string    appointSupProductId=0    stemFromSubOrderId=123456    externalBizId=456789
    postRequests    ${publicOrderUrl}    ${input_cs}    /api/Order    ${token}
    ${data}    get from dictionary    ${responsedata}    data
    ${orderid}    get from dictionary    ${data}    id
    sleep    6
    ${getdata}    create dictionary    Id=${orderid}    PageIndex=1    PageSize=1
    getRequests    ${publicOrderUrl}    ${getdata}    /api/Order/GetList    ${token}
    ${datalist}    get from dictionary    ${response_get_data}    data
    ${data}    get from dictionary    ${datalist}    list
    ${dict}    set variable    ${data}[0]
    ${orderOuterStatus}    get from dictionary    ${dict}    orderOuterStatus
    LOG    ---------------------獲取下單后的數量、餘額----------------------------------------------
    getAllData    0
    ${Cardnum2}    set variable    ${Cardnum}
    ${FPbalance2}    set variable    ${FPbalance}
    ${Pbalance2}    set variable    ${Pbalance}
    ${Sbalance2}    set variable    ${Sbalance}
    ${Jbalance2}    set variable    ${Jbalance}
    ${sprice}    set variable    ${sprice}
    ${price}    set variable    ${price}
    log    ------------------斷言-----------------------------------------------------------------
    ${Cardnum3}    Evaluate    ${Cardnum1}
    ${Jbalance3}    Evaluate    ${Jbalance1}
    ${Sbalance3}    Evaluate    ${Sbalance1}
    ${Pbalance3}    Evaluate    ${Pbalance1}
    should be true    ${orderOuterStatus}==90
    should be true    ${Cardnum3}==${Cardnum2}
    should be true    ${Jbalance3}==${Jbalance2}
    should be true    ${Sbalance3}==${Sbalance2}
    should be true    ${Pbalance3}==${Pbalance2}

7 集成到CICD流程

7.1 jenkins配置job
通過jenkins的參數化構建,定義it和pre兩套環境

jenkins發送RF執行的命令

7.2 封裝的jenkins_job的執行接口地址
通過python的flask框架,根據測試和pre兩套環境包一層jenkins的job執行接口

__author__ = 'paul'

# !/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, abort, request, jsonify
import jenkins

server = jenkins.Jenkins('http://10.0.1.xxx:80', username='xxx', password='fuluxxxx')

app = Flask(__name__)

tasks = []

# it的測試集合http請求接口
@app.route('/test/it', methods=['get'])
def robot_Test_It():
    server.build_job('CI_FuluOrder', {'environment': 'IT'})
    return jsonify({'result': 'success'})

# pre的測試集合http請求接口
@app.route('/test/pre', methods=['get'])
def robot_Test_Pre():
    server.build_job('CI_FuluOrder', {'environment': 'PRE'})
    return jsonify({'result': 'success'})

if __name__ == "__main__":
    # 將host設置為0.0.0.0,則外網用戶也可以訪問到這個服務
    app.run(host="0.0.0.0", port=80, debug=True)

7.3 將上述flask封裝的接口打包成鏡像
根據dockerfile生成鏡像

FROM python:3.6
WORKDIR /app
EXPOSE 80
COPY .	.
RUN pip install -r requirements.txt 
ENTRYPOINT ["python","robotTestApi.py"]

7.4 將鏡像部署到kubernetes,對外提供服務
供觸發測試執行的調用入口 ,這部分封裝的接口部署在本地的k8s集群下ordermiddle

IT: http://ordermiddle.xxx.cn/test/it
pre:http://ordermiddle.xxx.cn/test/pre

7.5 被測項目的CICD集成接口自動化測試
gitlab目前採取直接對CICD腳本加入測試步驟,在部署到容器30秒后(考慮到容器在K8S啟動時間)調用測試接口

7.6 發送測試報告

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

葡西法三國簽署能源互聯協議 法國將關閉所有煤電廠

摘錄自2018年7月28日新華社報導

葡萄牙、西班牙和法國27日在葡萄牙首都里斯本舉行的第二屆能源互聯峰會上正式簽署了三國能源互聯協議。

根據協議,西葡兩國同歐洲的能源互聯水平到2020年達到10%,2030年達到15%。此外,歐盟委員會將投資5.7億歐元在西班牙以北的比斯開灣建造一個用於連接西班牙、葡萄牙和法國的電力互聯項目。

葡萄牙總理科斯塔、西班牙首相桑切斯和法國總統馬克宏在會後舉行了聯合記者會。馬克宏表示,最晚到2022年,法國將關閉所有煤電廠。

科斯塔說,葡萄牙計劃到2020年使清潔能源占比超過60%,葡萄牙在逐步減少煤電行業投入的同時尋求清潔能源出口。

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

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

季節變化間顯現 科學家找到人為暖化的「指紋」

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

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

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

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

分類
發燒車訊

李澤楷收購菲斯科前夕遭遇萬向集團競購USB CONNECTOR,台北網頁設計,網站設計,南投搬家公司費用,新北清潔,貨運

據悉,去年11月,停產一年的美國電動車製造商菲斯科(Fisker)申請破產保護。香港商人李澤楷組成的財團以2500萬美元購入Fisker欠美國政府的未償還貸款,並計畫購入該電動汽車廠商的餘下資產。

按照原計劃,法院將於1月3日決定Fisker是否出售給李澤楷的關聯公司。不過,在交易得到美國法院首肯前夕,傳中國大陸萬向集團報價收購Fisker。

據外媒報導,Fisker 12月31日提交給法院的檔顯示,Fisker債權人已經要求法院廢止Fisker同意將資產售予李澤楷的交易,並開展公開競拍,而萬向集團旗下萬向美國公司將參與競購。萬向集團已經同意初步開出2472.5萬美元的報價,並承擔Fisker部分債務。

Fisker的產品為卡瑪插電式混合動力跑車,在美國市場售價高達10萬美元,但銷量一直不理想。據提交的檔顯示,萬向計畫最早在4月使Fisker恢復生產,並最終把製造業務從芬蘭遷回美國密西根州。

去年1月,萬向集團曾以2.566億美元的價格收購了美國最大的新能源電池製造商A123系統公司。而菲斯科此前是A123系統公司的最大客戶。

Fisker和A123兩家公司均獲得了美國能源部的綠色能源貸款,美國政府此前曾試圖阻撓把A123出售股權給萬向,因為美國監管方擔心敏感技術可能競爭對手手中。

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

豐田氫燃料電池車FCV明年先在加州地區上路

日本汽車龍頭豐田6日表示,將於2015年首先在美國市場推出具「零排放」功能的「氫燃料電池車」,此款車型名稱暫定為FCV,利用氫燃料電池做為動力來源,行駛時僅排放水蒸氣。該款車型的售價將控制在5~10萬美元之間。該款車型在日本市場的推出時間,料將與美國市場同步。豐田的競爭對手現代與本田也表示將於明年推出同類型的汽車。

豐田銷售副資深副總卡特(Bob Carter)表示,FCV在功能上屬於一般車型,是一款零排放、電力驅動、中型規格、4門轎車的車款,將配合加州政府的充電站政策,於當地優先推出。

豐田大幅改造氫燃料電池車的車型設計,使氫燃料電池在運作過程中,大幅降低對氧氣的需求。氫氣車在充滿電力後,可行駛300英里(約480公里)的車程。充電時間僅需費時3~5分鐘。

豐田近來與加州大學合作,表示最初的1萬輛氫氣車,僅有舊金山與聖地牙哥一帶的68座充電站,能夠支援氫燃料電力。但為方便未來的充電需求,加州政府已通過2億美元經費,規劃在2015年、2016年、與2024年,分別新增20座、40座,與100個充電站。卡特指出,如果設置適當,只須利用加州目前1萬座加油站當中的15%,將其轉型成氫燃料充電站,就可充分提供電力需求。

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

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

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

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

分類
發燒車訊

python動態柱狀圖圖表可視化:歷年軟科中國大學排行

本來想參照:https://mp.weixin.qq.com/s/e7Wd7aEatcLFGgJUDkg-EQ搞一個往年編程語言動態圖的,奈何找不到數據,有數據來源的歡迎在評論區留言。

這裏找到了一個,是2020年6月的編程語言排行,供大家看一下:https://www.tiobe.com/tiobe-index/

 

我們要實現的效果是:

大學排名來源:http://www.zuihaodaxue.com/ARWU2003.html

部分截圖:

在http://www.zuihaodaxue.com/ARWU2003.html中的年份可以選擇,我們解析的頁面就有了:

"http://www.zuihaodaxue.com/ARWU%s.html" % str(year)

初步獲取頁面的html信息的代碼:

def get_one_page(year):
    try:
        headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
            }
        url = "http://www.zuihaodaxue.com/ARWU%s.html" % str(year)
        response=requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.content
    except RequestException:
        print('爬取失敗')

我們在頁面上進行檢查:

數據是存儲在表格中的,這樣我們就可以利用pandas獲取html中的數據,基本語法:

tb = pd.read_html(url)[num]

其中的num是標識網頁中的第幾個表格,這裏只有一個表格,所以標識為0。初步的解析代碼就有了:

def parse_on_page(html,i):
    tb=pd.read_html(html)[0]
    return tb

我們還要將爬取下來的數據存儲到csv文件中,基本代碼如下:

def save_csv(tb):
    start_time=time.time()
    tb.to_csv(r'university.csv', mode='a', encoding='utf_8_sig', header=True, index=0)
    endtime = time.time()-start_time
    print('程序運行了%.2f秒' %endtime)

最後是一個主函數,別忘了還有需要導入的包:

import requests
from requests.exceptions import RequestException
import pandas as pd
import time
def main(year):
    for i in range(2003,year):
        html=get_one_page(i)
        tb=parse_on_page(html,i)
        #print(tb)
        save_csv(tb)
if __name__ == "__main__":
    main(2004)

運行之後,我們在同級目錄下就可以看到university.csv,部分內容如下:

存在幾個問題:

(1)缺少年份

(2)最後一列沒有用

(3)國家由於是圖片表示,沒有爬取下來

(4)排名100以後的是一個區間

我們接下來一一解決:

(1)刪掉沒用的列

def parse_on_page(html,i):
    tb=pd.read_html(html)[0]
    # 重命名表格列,不需要的列用數字錶示
    tb.columns = ['world rank','university', 2, 'score',4]
    tb.drop([2,4],axis=1,inplace=True)
    return tb

新的結果:

(2) 對100以後的進行唯一化,增加一列index作為排名標識

tb['index_rank'] = tb.index
tb['index_rank'] = tb['index_rank'].astype(int) + 1

(3)新增加年份

tb['year'] = i

(4)新增加國家

首先我們進行檢查:

發現國家在td->a>img下的圖像路徑中有名字:UnitedStates。 我們可以取出src屬性,並用正則匹配名字即可。

def get_country(html):
    soup = BeautifulSoup(html,'lxml')
    countries = soup.select('td > a > img')
    lst = []
    for i in countries:
        src = i['src']
        pattern = re.compile('flag.*\/(.*?).png')
        country = re.findall(pattern,src)[0]
        lst.append(country)
    return lst

然後這麼使用:

# read_html沒有爬取country,需定義函數單獨爬取
tb['country'] = get_country(html)

最終解析的整體函數如下:

def parse_on_page(html,i):
    tb=pd.read_html(html)[0]
    # 重命名表格列,不需要的列用數字錶示
    tb.columns = ['world rank','university', 2, 'score',4]
    tb.drop([2,4],axis=1,inplace=True)
    tb['index_rank'] = tb.index
    tb['index_rank'] = tb['index_rank'].astype(int) + 1
    tb['year'] = i
    # read_html沒有爬取country,需定義函數單獨爬取
    tb['country'] = get_country(html)
    return tb

運行之後:

最後我們要提取屬於中國部分的相關信息:

首先將年份改一下,獲取到2019年為止的信息:

if __name__ == "__main__":
    main(2019)

然後我們提取到中國高校的信息,直接看代碼理解:

def analysis():
    df = pd.read_csv('university.csv')
    # 包含港澳台
    # df = df.query("(country == 'China')|(country == 'China-hk')|(country == 'China-tw')|(country == 'China-HongKong')|(country == 'China-Taiwan')|(country == 'Taiwan,China')|(country == 'HongKong,China')")[['university','year','index_rank']]

    # 只包括內地
    df = df.query("(country == 'China')")
    df['index_rank_score'] = df['index_rank']
    # 將index_rank列轉為整形
    df['index_rank'] = df['index_rank'].astype(int)

    # 美國
    # df = df.query("(country == 'UnitedStates')|(country == 'USA')")

    #求topn名
    def topn(df):
        top = df.sort_values(['year','index_rank'],ascending = True)
        return top[:20].reset_index()
    df = df.groupby(by =['year']).apply(topn)

    # 更改列順序
    df = df[['university','index_rank_score','index_rank','year']]
    # 重命名列
    df.rename (columns = {'university':'name','index_rank_score':'type','index_rank':'value','year':'date'},inplace = True)

    # 輸出結果
    df.to_csv('university_ranking.csv',mode ='w',encoding='utf_8_sig', header=True, index=False)
    # index可以設置

本來是想爬取從2003年到2019年的,運行時發現從2005年開始,頁面不一樣了,多了一列:

方便起見,我們就只從2005年開始了,還需要修改一下代碼:

    # 重命名表格列,不需要的列用數字錶示
    tb.columns = ['world rank','university', 2,3, 'score',5]
    tb.drop([2,3,5],axis=1,inplace=True)

最後是整體代碼:

import requests
from requests.exceptions import RequestException
import pandas as pd
import time
from bs4 import BeautifulSoup
import re
def get_one_page(year):
    try:
        headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
            }
        url = "http://www.zuihaodaxue.com/ARWU%s.html" % str(year)
        response=requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.content
    except RequestException:
        print('爬取失敗')
def parse_on_page(html,i):
    tb=pd.read_html(html)[0]
    # 重命名表格列,不需要的列用數字錶示
    tb.columns = ['world rank','university', 2,3, 'score',5]
    tb.drop([2,3,5],axis=1,inplace=True)
    tb['index_rank'] = tb.index
    tb['index_rank'] = tb['index_rank'].astype(int) + 1
    tb['year'] = i
    # read_html沒有爬取country,需定義函數單獨爬取
    tb['country'] = get_country(html)
    return tb
def save_csv(tb):
    start_time=time.time()
    tb.to_csv(r'university.csv', mode='a', encoding='utf_8_sig', header=True, index=0)
    endtime = time.time()-start_time
    print('程序運行了%.2f秒' %endtime)
# 提取國家名稱
def get_country(html):
    soup = BeautifulSoup(html,'lxml')
    countries = soup.select('td > a > img')
    lst = []
    for i in countries:
        src = i['src']
        pattern = re.compile('flag.*\/(.*?).png')
        country = re.findall(pattern,src)[0]
        lst.append(country)
    return lst
def analysis():
    df = pd.read_csv('university.csv')
    # 包含港澳台
    # df = df.query("(country == 'China')|(country == 'China-hk')|(country == 'China-tw')|(country == 'China-HongKong')|(country == 'China-Taiwan')|(country == 'Taiwan,China')|(country == 'HongKong,China')")[['university','year','index_rank']]

    # 只包括內地
    df = df.query("(country == 'China')")
    df['index_rank_score'] = df['index_rank']
    # 將index_rank列轉為整形
    df['index_rank'] = df['index_rank'].astype(int)

    # 美國
    # df = df.query("(country == 'UnitedStates')|(country == 'USA')")

    #求topn名
    def topn(df):
        top = df.sort_values(['year','index_rank'],ascending = True)
        return top[:20].reset_index()
    df = df.groupby(by =['year']).apply(topn)

    # 更改列順序
    df = df[['university','index_rank_score','index_rank','year']]
    # 重命名列
    df.rename (columns = {'university':'name','index_rank_score':'type','index_rank':'value','year':'date'},inplace = True)

    # 輸出結果
    df.to_csv('university_ranking.csv',mode ='w',encoding='utf_8_sig', header=True, index=False)
    # index可以設置
def main(year):
    for i in range(2005,year):
        html=get_one_page(i)
        tb=parse_on_page(html,i)
        save_csv(tb)
        print(i,'年排名提取完成完成')
        analysis()
if __name__ == "__main__":
    main(2019)

運行之後會有一個university_ranking.csv,部分內容如下:

接下來就是可視化過程了。

1、 首先,到作者的github主頁:  
https://github.com/Jannchie/Historical-ranking-data-visualization-based-on-d3.js

2、克隆倉庫文件,使用git

# 克隆項目倉庫
git clone https://github.com/Jannchie/Historical-ranking-data-visualization-based-on-d3.js
# 切換到項目根目錄
cd Historical-ranking-data-visualization-based-on-d3.js
# 安裝依賴
npm install

這裏如果git clone超時可參考:

https://www.cnblogs.com/xiximayou/p/12305209.html

需要注意的是,這裏的npm是我之前裝node.js裝了的,沒有的自己需要裝一下。

在執行npm install時會報錯:

先執行:

npm init

之後一直回車即可:

再執行npm install

任意瀏覽器打開bargraph.html網頁,點擊選擇文件,然後選擇前面輸出的university_ranking.csv文件,看下效果:

只能製作動圖上傳了。

可以看到,有了大致的可視化效果,但還存在很多瑕疵,比如:表順序顛倒了、字體不合適、配色太花哨等。可不可以修改呢?

當然是可以的,只需要分別修改文件夾中這幾個文件的參數就可以了:

  • config.js 全局設置各項功能的開關,比如配色、字體、文字名稱、反轉圖表等等功能;

  • color.css 修改柱形圖的配色;

  • stylesheet.css 具體修改配色、字體、文字名稱等的css樣式;

  • visual.js 更進一步的修改,比如圖表的透明度等。

知道在哪裡修改了以後,那麼,如何修改呢?很簡單,只需要簡單的幾步就可以實現:

  • 打開網頁,右鍵-檢查,箭頭指向想要修改的元素,然後在右側的css樣式表裡,雙擊各項參數修改參數,修改完元素就會發生變化,可以不斷微調,直至滿意為止。

    

  • 把參數複製到四個文件中對應的文件里並保存。

  • Git Bash運行npm run build,之後刷新網頁就可以看到優化后的效果。(我發現這一步其實不需要,而且會報錯,我直接修改config.js之後運行也成功了)

這裏我主要修改的是config.js的以下項:

  // 倒序,使得最短的條位於最上方 
  reverse: true,
  // 附加信息內容。
  // left label
  itemLabel: "本年度第一大學",
  // right label
  typeLabel: "世界排名",
  //為了避免名稱重疊
  item_x: 500,
  // 時間標籤坐標。建議x:1000 y:-50開始嘗試,默認位置為x:null,y:null
  dateLabel_x: 1000,
  dateLabel_y: -50,

最終效果:

至此,就全部完成了。

看起來簡單,還是得要自己動手才行。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

搶先日產 比亞迪全電動計程車隊進入倫敦

中國汽車廠商比亞迪(BYD)今(11)日宣布,首支英國倫敦史上全電動計程車隊正式上路,在2018年前批量供應零排放出租車的競爭中,搶在了日產(Nissan)等國際競爭對手之前。不到2個月前,比亞迪還交付了倫敦史上首批全電動公共汽車。

據《金融時報》報導,倫敦市長鮑里斯約翰遜(Boris Johnson)設定了全市計程車必須在2018年前實現零排放的目標,引發汽車廠商爭相開發新車。

比亞迪趕在該期限之前率先打入了倫敦交通市場。比亞迪將推出20輛電動汽車組成的車隊,由出租車公司Thriev營運。

另一方面,日本電動車廠商日產(Nissan)與英國經典黑出租車製造商倫敦出租車公司(London Taxi Company) ,也準備趕在2018年期限之前開發出全電動車型。

著名的股神華倫•巴菲特(Warren Buffett)持有比亞迪9.9%股份。

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

分類
發燒車訊

萬向集團出價1.49億美元 最終競得菲斯科

據外電報道,中國汽車零件製造商萬向集團擊敗李澤楷旗下的Hybrid Tech,在美國豪華混合動力汽車製造商Fisker的破產資產拍賣中勝出。萬向出價1.492億美元,大約是Fisker最初尋求的收購價的6倍。

這次拍賣持續了三天,經歷了19輪投標。美國破產法官Kevin Gross按計劃將於2月18日批准此次出售。

菲斯科在2009年獲得了美國能源部的5.29億美元綠色貸款。但能源部在2011年中期凍結支付,稱菲斯科在開發新車型上狀況頻出,一再拖延。

2013年11月,菲斯科申請破產,並要求破產法官準許Hybrid Tech以2500萬美元的低價,向美國能源部購入Fisker原本總值1.6億多美元的貸款。Hybrid Tech從而成為Fisker的高級擔保貸款人,更表明有意進一步收購Fisker。

但無擔保債權人反對這一報價,從而幫助中國最大的汽車零部件供應商於12月進入到交易環節中。

在此筆交易達成后,萬向集團將努力重振菲斯科在中國汽車市場的發展,該集團也獲得了一個打進美國市場的入口點。據資料顯示,萬向為中國投資美國製造業、新能源和房地產的先行者,在過去20年,萬向於美國的投資遍布美國14個州,涉及汽車零件製造、不動產、新能源和私募基金等。

2012年底時,萬向曾以近2.6億美元擊敗江森自控,成功拍得美國破產電池生產商A123鋰電池公司資產,這家公司正是Fisker的電池供應商。經營汽車零部件業務的萬向集團一直期望進軍整車制造領域。

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

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

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

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