因中國反對 鋼鐵產能過剩全球論壇不再續辦

摘錄自2019年10月29日TVBS新聞報導

日本經濟新聞中文網報導,中國、日美歐等33個國家和地區當地時間10月26日在東京召開鋼鐵產能過剩全球論壇的部長級會議。出席論壇的日本經濟產業相梶山弘志在記者會上表示,今後將呼籲中國透過雙邊會談等方式來應對鋼鐵方面的問題。

但由於中國強烈反對論壇延續,該論壇將在2019年到期後終止。

中國官媒新華社在報導中解釋稱,中方認為,論壇到期後結束具有充分的依據和理由。論壇工作職責文件規定,論壇期限為3年,在全體成員協商一致基礎上,可以延長。

此外,新華社引述中方意見表示,中國鋼鐵生產主要滿足國內市場需求。雖然中國鋼鐵產能和產量占全球一半,但中國鋼鐵的消費量也接近全球一半,目前產量的93%用於滿足國內市場的需求,鋼材出口占產量的比例只有7%,沒有衝擊國際市場。

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

【其他文章推薦】

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

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

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

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

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

北京路燈變充電樁 望每天為一萬輛車充電

北京市首批路燈充電樁改造已經展開,位於昌平區京密北路上的八十八盞路燈,從傳統高壓鈉燈改造為LED燈,可讓十幾輛電動汽車同時充電;此外,昌平區內還設置了八個純電動汽車慢充樁,專供電動車充電,充電時間約為四、五個小時,且白天晚上皆可充電。北京市科委指出,希望今年內能達成北京五環內建成五公里半徑的快速充電網路和每天為一萬輛車充電的目標。   除北京市內,連接北京與上海全程1262公里的京滬高速公路也將開通全線快速充電系統。平均每五十公里將設一座充電站,最快三十分鐘可充電完成。同等里程電費支出為燃油車的一半,全程充電費不到人民幣400元(約合新臺幣2052元)。   目前中國大陸的國家電網已完成2.4萬個充電樁,形成「兩縱一橫」網路,規模為世界之最。但據報導,其目前已建成的四百多座充電站幾乎沒有盈利,處於全線虧損,而在深圳市營運的七座充電站,每年虧損額超過1000萬人民幣(約5132.3萬元)。

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

【其他文章推薦】

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

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

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

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

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

IOT設備SmartConfig實現

一般情況下,IOT設備(針對wifi設備)在智能化過程中需要連接到家庭路由。但在此之前,需要將wifi信息(通常是ssid和password,即名字和密碼)發給設備,這一步驟被稱為配網。移動設備如Android、iOS等扮演發送wifi信息的角色,簡單來說就是移動應用要與IOT設備建立通信,進而交換數據。針對配網這一步驟,市面上一般有兩種做法:

  • AP連接方式:IOT設備發出AP(Access Point,可理解為路由器,可發出wifi)信息;移動設備STA(Station,可以連接wifi)連接到IOT設備AP,接着就可以發送wifi(家庭路由的wifi)信息給設備了。另外,也可互換角色,及移動設備釋放熱點,IOT設備進行連接。
  • SmartConfig(一鍵配置)方式:不需要建立連接,移動設備將wifi信息(需提前獲取)寫入數據包,組播循環發出此數據包;IOT設備處於監聽所有網絡的模式,接收到UDP包后解析出wifi信息拿去連網。

可以發現,SmartConfig不需建立連接,步驟較少,實現起來也較容易,並且用戶也無需進行過多的操作。本文的IOT設備基於ESP32開發板,解釋原理及實現如何通過Android APP發出UDP包實現SmartConfig。知識點:計算機網絡、UDP、組播、DatagramSocket

一、網絡知識回顧

計算機網絡分層結構如下:

  • 應用層:體系中的最高層。任務是通過應用程序間的交互來完成特定網絡應用。不同的網絡應用對應不同的協議:如HTTPDNSSMTP。其交互的數據單元稱為報文。
  • 運輸層:複雜向兩台主機中進程直接的通信提供通用的數據傳輸服務,使用端口作為向上傳遞的進程標識,主要有TCP和UDP。
  • 網絡層:負責為分組交換網絡上的不同主機提供通信服務,使用IP協議。
  • 網絡接口層:包括數據鏈路層和物理層,傳輸單位分別是幀和比特。

1. IP協議

IP(Internet Protocol)協議是網絡層的主要協議。其版本有IPv4(32位)、IPv6(128位)。與IP協議配套使用的還有地址解析協議(ARP)、網際控制報文協議(ICMP,重要應用即常見的PING,測試連通性)、網際組管理協議(IGMP)。

IP數據報格式,由首部和數據部分兩部分組成:

IP地址分類如下:

1.1 兩級IP地址

IP地址是每一台主機唯一的標識符,由網絡號和主機號組成。A、B、C三類均為單播地址(一對一),D類為多播地址(一對多)。

1.2 三級IP地址

在兩級中新增了子網號字段,也稱為劃分子網。其方法是從主機號借用若干位作為子網號。

子網掩碼:是一個網絡或子網的重要屬性,可通過子網掩碼計算出目的主機所處於哪一個子網。若沒有劃分子網,則使用默認子網掩碼(A類255.0.0.0、B類255.255.0.0、C類255.255.255.0)

1.3 無分類編址

無分類編址(CIDR)也稱為構造超網,使用網絡前綴+主機號規則,並使用斜線標明前綴位數,如:

128.15.34.77/20
1.4 IP多播

多播又稱為組播,提供一對多的通信,大大節約網絡資源。IP數據報中不能寫入某一個IP地址,需寫入多播組的標識符(需要接收的主機與此標識符關聯)。D類地址即為多播組的標識符,所以多播地址(D類)只能作為目的地址。分為本局域網上的硬件多播、互聯網多播兩種。

多播使用到的協議

  • IGMP(網際組管理協議):讓連接在本地局域網上的多播路由器(能夠運行多播協議的路由器)知道本局域網上是否有主機(進程)參加或退出了某個多播組。
  • 多播路由選擇協議:用於多播路由器之間的協同工作,以便讓多播數據報以最小的代價傳輸。

2. UDP協議

運輸層向上面的應用層提供通信服務,通信的端點並不是主機而是主機中進程,使用協議端口號標識進程(如HTTP為80)。UDP協議是運輸層中重要的兩個協議之一。

  • UDP是無連接的
  • UDP使用盡最大努力交付,不保證可靠交付
  • UDP是面向報文的
  • UDP沒有擁塞控制
  • UDP支持一對一,一對多,多對一和多對多
  • UDP首部開銷小

二、Java中的UDP

1. Socket

socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層複雜的操作抽象為幾個簡單的接口供應用層調用已實現進程在網絡中通信。簡單來說,socket是一種接口,對傳輸層(TCP/UPD協議)進行了的封裝。

socket通信

  • TCP socket:需建立連接,TCP三次握手,基於流的通信(InputStrea和OutputStream)
  • UDP socket:無需建立連接,基於報文的通信。可以組播的形式發出報文,適合本場景中的配網步驟。

2. Java中的socket

2.1 類解釋

Java為Socket編程封裝了幾個重要的類(均為客戶端-服務端模式):

Socket
實現了一個客戶端socket,作為兩台機器通信的終端,默認採用TCP。connect()方法請求socket連接、getXXXStream()方法獲取輸入/出流、close()關閉流。

ServerSocket
實現了一個服務器的socket,等待客戶端的連接請求。bind()方法綁定一個IP地址和端口、accept()方法監聽並返回一個Socket對象(會阻塞)、close()關閉一個socket

SocketAddress # InetSocketAddress
前者是一個抽象類,提供了一個socket地址,不關心傳輸層協議;後者繼承自前者,表示帶有IP地址和端口號的socket地址。

DatagramSocket
實現了一個發送和接收數據報的socket,使用UDP。send()方法發送一個數據報(DatagramPacket)、receive()方法接收一個數據報(一直阻塞接至收到數據報或超時)、close()方法關閉一個socket。

DatagramPacket
使用DatagramSocket時的數據報載體。

2.2 UDP實例

SmartConfig採用UDP實現,所以在前述知識的基礎下,先編寫一個例子熟悉java udp的使用,首先建立服務端的代碼:

public class UDPServer {
    /**
     * 設置緩衝區的長度
     */
    private static final int BUFFER_SIZE = 255;
    /**
     * 指定端口,客戶端需保持一致
     */
    private static final int PORT = 8089;

    public static void main(String[] args) {
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket(PORT);
            DatagramPacket datagramPacket = new DatagramPacket(new byte[BUFFER_SIZE], BUFFER_SIZE);
            while (true) {
                // 接收數據報,處於阻塞狀態
                datagramSocket.receive(datagramPacket);
                System.out.println("Receive data from client:" + new String(datagramPacket.getData()));
                // 服務器端發出響應信息
                byte[] responseData = "Server response".getBytes();
                datagramPacket.setData(responseData);
                datagramSocket.send(datagramPacket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }
    }
}

客戶端發出數據報:

public class UDPClient {
    /**
     * 指定端口,與服務端保持一致
     */
    private static final int PORT = 8089;
    /**
     * 超時重發時間
     */
    private static final int TIME_OUT = 2000;
    /**
     * 最大重試次數
     */
    private static final int MAX_RETRY = 3;

    public static void main(String[] args) throws IOException {
        try {
            byte[] sendMsg = "Client msg".getBytes();
            // 創建數據報
            DatagramSocket socket = new DatagramSocket();
            // 設置阻塞超時時間
            socket.setSoTimeout(TIME_OUT);
            // 創建server主機的ip地址(此處使用了本機地址)
            InetAddress inetAddress = InetAddress.getByName("192.168.xxx.xxx");
            // 發送和接收的數據報文
            DatagramPacket sendPacket = new DatagramPacket(sendMsg, sendMsg.length, inetAddress, PORT);
            DatagramPacket receivePacket = new DatagramPacket(new byte[sendMsg.length], sendMsg.length);
            // 數據報文可能丟失,設置重試計數器
            int tryTimes = 0;
            boolean receiveResponse = false;
            // 將數據報文發送出去
            socket.send(sendPacket);
            while (!receiveResponse && (tryTimes < MAX_RETRY)) {
                try {
                    // 阻塞接收數據報文
                    socket.receive(receivePacket);
                    // 檢查返回的數據報文
                    if (!receivePacket.getAddress().equals(inetAddress)) {
                        throw new IOException("Unknown server's data");
                    }
                    receiveResponse = true;
                } catch (InterruptedIOException e) {
                    // 重試
                    tryTimes++;
                    System.out.println("TimeOut, try " + (MAX_RETRY - tryTimes) + " times");
                }
            }
            if (receiveResponse) {
                System.out.println("Receive from server:" + new String(receivePacket.getData()));
            } else {
                System.out.println("No data!");
            }
            socket.close();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
}

運行結果:

* 發現客戶端收到的數據被截斷了,這是因為沒有重置接收包的長度,在服務端datagramPacket.setLength()可解決。

三、SmartConfig

根據前面的socket相關應用,基本想到如何實現一鍵配置。在實際應用中,原理一樣,只是增加了組播(這一點需要和IOT設備端共同確定,數據的格式也需協定)。在實現中,需要針對不同IP組播地址發出循環的UDP報文,增加設備端接收到的可能性;同時APP也要開啟服務端程序監聽發出數據報的響應,以此更新UI或進行下一步的數據通信。相關核心代碼如下:

// 對每一個組播地址循環發出報文 
while (!mIsInterrupt && System.currentTimeMillis() - currentTime < mParameter
         .getTimeoutGuideCodeMillisecond()) {
     mSocketClient.sendData(gcBytes2,
             mParameter.getTargetHostname(),
             mParameter.getTargetPort(),
             mParameter.getIntervalGuideCodeMillisecond());
     // 跳出條件,發出UDP報文達到一定時間
     if (System.currentTimeMillis() - startTime > mParameter.getWaitUdpSendingMillisecond()) {
         break;
     }
}

組播地址設置:

public String getTargetHostname() {
    if (mBroadcast) {
        return "255.255.255.255";
    } else {
        int count = __getNextDatagramCount();
        return "234." + (count + 1) + "." + count + "." + count;
    }
}

完整代碼省略(利益相關,代碼匿了^_^),基本思路很簡單。最終的實現是IOT設備收到UDP發出的wifi信息,並以此成功連接wifi,連接服務器,進而綁定賬號。

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

【其他文章推薦】

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

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

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

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

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

福斯邁入新紀元 新一代電動車量產

摘錄自2019年11月5日中央社報導

德國汽車大廠福斯新一代的純電動車ID.3,5日開始量產,象徵福斯正式邁入電動車時代。福斯還打算在未來10年推出70款純電動車,有機會超越特斯拉成為全球主要的電動車製造商。

福斯執行長迪斯(Herbert Diess)表示,業界已經沒有人懷疑電動車能不能成功,問題是多快能實現,以及先在世界上哪個地區實現,他相信德國汽車工業在電動車時代依然能保住領先地位。

ID.3是福斯進入電動車時代的象徵,在集團歷史上的地位相當於金龜車和Golf車款,被福斯寄與厚望。ID.3續航力300公里上下的入門款,最低售價3萬歐元(約新台幣100萬元),在德國因此有「國民電動車」之稱,預計明年夏天開始交貨,

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

【其他文章推薦】

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

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

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

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

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

日本充電樁達4萬個 超傳統加油站

日產汽車(Nissan)日前宣佈,目前日本全國有4萬個充電設施,其中包括家用充電站,而加油站只有3.4萬個,充電樁數量已超過傳統加油站。   去年5月,豐田、日產、本田、三菱這四大日本汽車製造商與日本政策投資銀行共同成立了“日本充電服務”公司,承擔起在商業設施等地設置充電樁的成本及8年內充電樁的維護費用。   日本便利店巨頭也表示將加快完善電動車充電設施,期待以此增加客流量。全家便利店在今年3月底之前將可為電動車及插電式混合動力車快速充電的店鋪增加至650家,期待達到同行業數量之最,並成為首個能源補給設施遍佈日本全境的便利店企業。羅森便利店也計畫在今年5月前將電動車充電樁由目前的12個增至200個左右。

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

【其他文章推薦】

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

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

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

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

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

關於技術文章“標題黨”一事我想說兩句

閱讀本文大概需要 1.8 分鐘。

前天發表的一篇文章,標題是:“面試官:你剛說你喜歡研究新技術,那麼請說說你對 Blazor 的了解”。確實,這篇文章有標題黨的味道,如果因此給部分童鞋帶來不適,我在這先真誠地給大家道個歉!

這篇文章同步發表到博客園后,評論熱鬧了,其中“懟”文章是標題黨的不在少數。我先把與標題黨相關的評論截圖貼出來大家看看。

上面只截了與“標題黨”相關的部分,一些討論技術的沒有包含在截圖裡。截止目前,評論大概有近 20 條,感興趣的可以去博客園看看那些有想法的優質評論。害,平時寫的技術文章很少見有這麼熱鬧的評論。

評論中的 1 樓,@memmon 表達了博客園標題黨現象的看法。由於支持的人比較多,我再次引用一下:

作為一個每天都會瀏覽博客園的用戶,不知道是不是我心態變了,現在看博客園 cnblog 幾乎看不下去了,一進去幾乎就不想看,全是標題黨,我搞不清楚這些人怎麼想的,在專業領域需要標題黨嗎,好的不學,全是網紅那一套,這些流量有什麼意義,標題幾乎是對話式的,百度貼吧的既視感,本來應該是知乎寫文章的態度,進去全是百度貼吧式的文章標題,我知道寫文章很悶,苦中作樂,自我調侃都是方式,不過觀感真的不太好。

說的很中肯,語氣委婉客氣,並沒有多少“懟”的意思。當然他說的不是特別針對我這一篇文章,而是表達對博客園這種現象的“看不下去”。我理解他的心情,我也反感標題黨。

我看到評論后回復了 @memmon:

謝謝點評,接受一切批評指導,並會努力提升文章質量。本文確實有標題黨味道,但行文並沒有離題,確實是從群里大家最近聊面試的話題中產生寫本文的 Idea,目的是幫助那些正在面試的人了解一下 Blazor。也有想過把文章標題改成:“Blazor 介紹”,但又覺得有點太教科書了,技術文章本就枯燥,偶爾苦中作樂調劑一下我覺得挺好。這不,這麼一調劑,大家討論的熱情就上來了。

我接着說兩句。

標題黨在前兩三年很盛行,人人痛恨。但近一兩年見得越來越少了(只要你的興趣不和長輩們一致應該是很少看到標題黨了),說明自媒體人都意識到“標題黨”的危害。真正的“標題黨”文章雖然能在短時間內獲得一些點擊量,但稍微長遠一點來看,肯定引起讀者的反感,反而造成一大波真正的內容閱讀者取消關注。我,能不明白這個道理嗎。

我也幾乎每天都會看看博客園,博客園首頁的文章我並沒有發現什麼標題黨。惟一讓我印象深刻的是下面這類的所謂的“標題黨”文章:

  • 標題:震驚!Windows Service 服務和定時任務框架 quartz 之間原來是這種關係 ……
    地址:cnblogs.com/xiongze520/p/13031944.html
  • 標題:CPU 瞞着內存竟干出這種事
    地址:cnblogs.com/xuanyuan/p/12894711.html
  • 標題:完了!CPU 一味求快出事兒了!
    地址:cnblogs.com/xuanyuan/p/12856598.html
  • … 類似的還有很多。

我真心覺得這類標題挺有意思的,很贊,也很高級。如果是乾巴巴的教科書式的標題,我對文章一點興趣都沒有,不大可能會點進去看。但遇到這種標題,我極大可能會點進去看看,而且大多時候會認真地看完。對我來說,能讓我產生好奇或興趣、能讓我這顆浮躁的心不經意間讀完一篇技術文章,我就很感謝作者了。而且,作者深知要和短視頻、美女圖、搞笑動圖這樣能給人帶來既視快感的作品搶讀者的注意力是非常非常難的。為了能吸引我們一點點的注意力,為了能促使我們去閱讀一點更有營養的內容,技術文章“標題黨”作者也是想盡了辦法,難道我們不應該為作者的努力點個贊嗎?

技術文章的目標讀者又不是小學畢業沒文化,幾乎都是 Geek 好嗎。為了能激起 Geek 們的熱情,能讓他們多表達一個句話,你知道有多難嗎。你去公眾號和頭條對比一下那些技術文章的評論量和那些生活情感類文章的評論量,一篇技術文章能有 20 幾條評論那就相當熱鬧了。Geek 們豈是你能用標題吸引他們加關注的,只是帶來短暫的點擊量罷了。內容沒有營養,再標題黨也不會讓 Geek 們買賬,他們反而分分鐘取關你!你看,作為原創作者,我們也不容易吧。​ 偶爾“標題黨”調劑一下,能激起大家討論的興趣,能讓氛圍熱鬧一點,我覺得是好事情啊。

本就枯燥的技術文章,太在意標題,你就輸了。我是說,你真的把文章閱讀完了嗎?把你浮躁的心收起來吧,認真閱讀完文章后,在內容相關話題上表達自己的觀點和想法或提出意見,才是一個技術人應該有的態度,真正有收穫才算贏了自己,不是嗎。

最後,本號一定努力提高文章質量,堅持創作優質內容。一路走來,謝謝各位陪伴與支持!沒有你們,我也沒有持續寫作的動力。​

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

【其他文章推薦】

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

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

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

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

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

川普政府下月出租阿拉斯加土地 開放挖石油

摘錄自2019年11月6日中央社外電報導

美國總統川普政府今天(6日)表示,下月將開放標租阿拉斯加州北極地區近400萬英畝(160萬公頃)的土地,供作石油開發用途。政府並承諾未來會開放更多土地以供開發。

路透社報導,美國土地管理局(Bureau of Land Management)宣布12月11日將舉行阿拉斯加國家石油儲備區(National Petroleum Reserve in Alaska)年度石油與天然氣租賃權拍賣。這將是土地管理局為該區舉行的第15場石油租賃權拍賣。

土地管理局也即將完成一項計畫草案,準備推翻前總統歐巴馬時期的保護措施。

相關保護措施讓這塊2300萬英畝(930萬公頃)的國家石油儲備區,有大約一半不得進行石油開發,理由為必須保護北美馴鹿、候鳥,以及對區內原住民和國家而言很重要的其他資源。

川普政府與石油產業則主張,歐巴馬政府計畫的限制過多,必須用新計畫加以取代。

阿拉斯加國家石油儲備區位於阿拉斯加州北坡地區(North Slope)西側,地處普魯赫灣油田(Prudhoe Bay)和庫帕勒克油田(Kuparuk)西方。

近期幾項新發現已促使北坡地區石油開發行動往西擴張。阿拉斯加國家石油儲備區作為單位面積最大的美國聯邦土地,也被視為阿拉斯加州新的產油潛力區。

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

【其他文章推薦】

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

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

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

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

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

在 Spring Boot 中使用 HikariCP 連接池

上次幫小王解決了如何在 Spring Boot 中使用 JDBC 連接 MySQL 后,我就一直在等,等他問我第三個問題,比如說如何在 Spring Boot 中使用 HikariCP 連接池。但我等了四天也沒有等到任何音訊,似乎他從我的世界里消失了,而我卻仍然沉醉在他拍我馬屁的美妙感覺里。

突然感覺,沒有小王的日子里,好空虛。怎麼辦呢?想來想去還是寫文章度日吧,积極創作的過程中,也許能夠擺脫對小王的苦苦思念。寫什麼好呢?

想來想去,就寫如何在 Spring Boot 中使用 HikariCP 連接池吧。畢竟實戰項目當中,肯定不能使用 JDBC,連接池是必須的。而 HikariCP 據說非常的快,快到 Spring Boot 2 默認的數據庫連接池也從 Tomcat 切換到了 HikariCP(喜新厭舊的臭毛病能不能改改)。

HikariCP 的 GitHub 地址如下:

https://github.com/brettwooldridge/HikariCP

目前星標 12K,被使用次數更是達到了 43.1K。再來看看它的自我介紹。

牛逼的不能行啊,原來 Hikari 來源於日語,“光”的意思,這意味着快得像光速一樣嗎?講真,看簡介的感覺就好像在和我的女神“湯唯”握手一樣刺激和震撼。

既然 Spring Boot 2 已經默認使用了 HikariCP,那麼使用起來也相當的輕鬆愜意,只需要簡單幾個步驟。

01、初始化 MySQL 數據庫

既然要連接 MySQL,那麼就需要先在電腦上安裝 MySQL 服務(本文暫且跳過),並且創建數據庫和表。

CREATE DATABASE `springbootdemo`;
DROP TABLE IF EXISTS `mysql_datasource`;
CREATE TABLE `mysql_datasource` (
  `id` varchar(64NOT NULL,
  PRIMARY KEY (`id`)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

02、使用 Spring Initlallzr 創建 Spring Boot 項目

創建一個 Spring Boot 項目非常簡單,通過 Spring Initlallzr(https://start.spring.io/)就可以了。

勾選 Web、JDBC、MySQL Driver 等三個依賴。

1)Web 表明該項目是一個 Web 項目,便於我們直接通過 URL 來實操。

3)MySQL Driver:連接 MySQL 服務器的驅動器。

5)JDBC:Spring Boot 2 默認使用了 HikariCP,所以 HikariCP 會默認在 spring-boot-starter-jdbc 中附加依賴,因此不需要主動添加 HikariCP 的依賴。

PS:怎麼證明這一點呢?項目導入成功后,在 pom.xml 文件中,按住鼠標左鍵 + Ctrl 鍵訪問 spring-boot-starter-jdbc 依賴節點,可在 spring-boot-starter-jdbc.pom 文件中查看到 HikariCP 的依賴信息。

選項選擇完后,就可以點擊【Generate】按鈕生成一個初始化的 Spring Boot 項目了。生成的是一個壓縮包,導入到 IDE 的時候需要先解壓。

03、編輯 application.properties 文件

項目導入成功后,等待 Maven 下載依賴,完成后編輯 application.properties 文件,配置 MySQL 數據源信息。

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springbootdemo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

是不是有一種似曾相識的感覺(和[上一篇]()中的數據源配置一模一樣)?為什麼呢?答案已經告訴過大家了——默認、默認、默認,重要的事情說三遍,Spring Boot 2 默認使用了 HikariCP 連接池。

04、編輯 Spring Boot 項目

為了便於我們查看 HikariCP 的連接信息,我們對 SpringBootMysqlApplication 類進行編輯,增加以下內容。

@SpringBootApplication
public class HikariCpDemoApplication implements CommandLineRunner {
    @Autowired
    private DataSource dataSource;

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

    @Override
    public void run(String... args) throws Exception {
        Connection conn = dataSource.getConnection();
        conn.close();
    }
}

HikariCpDemoApplication 實現了 CommandLineRunner 接口,該接口允許我們在項目啟動的時候加載一些數據或者做一些事情,比如說我們嘗試通過 DataSource 對象與數據源建立連接,這樣就可以在日誌信息中看到 HikariCP 的連接信息。CommandLineRunner 接口有一個方法需要實現,就是我們看到的 run() 方法。

通過 debug 的方式,我們可以看到,在項目運行的過程中,dataSource 這個 Bean 的類型為 HikariDataSource。

05、運行 Spring Boot 項目

接下來,我們直接運行 HikariCpDemoApplication 類,這樣一個 Spring Boot 項目就啟動成功了。

HikariDataSource 對象的連接信息會被打印出來。也就是說,HikariCP 連接池的配置啟用了。快給自己點個贊。

06、為什麼 Spring Boot 2.0 選擇 HikariCP 作為默認數據庫連接池

有幾種基準測試結果可用來比較HikariCP和其他連接池框架(例如c3p0dbcp2tomcatvibur)的性能。例如,HikariCP團隊發布了以下基準(可在此處獲得原始結果):

HikariCP 團隊為了證明自己性能最佳,特意找了幾個背景對比了下。不幸充當背景的有 c3p0、dbcp2、tomcat 等傳統的連接池。

從上圖中,我們能感受出背景的尷尬,HikariCP 鶴立雞群了。HikariCP 製作以如此優秀,原因大致有下面這些:

1)字節碼級別上的優化:要求編譯后的字節碼最少,這樣 CPU 緩存就可以加載更多的程序代碼。

HikariCP 優化前的代碼片段:

public final PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
{
    return PROXY_FACTORY.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames));
}

HikariCP 優化后的代碼片段:

public final PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
{
    return ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames));
}

以上兩段代碼的差別只有一處,就是 ProxyFactory 替代了 PROXY_FACTORY,這個改動后的字節碼比優化前減少了 3 行指令。具體的分析參照 HikariCP 的 Wiki 文檔。

2)使用自定義的列表(FastStatementList)代替 ArrayList,可以避免 get() 的時候進行範圍檢查,remove() 的時候從頭到尾的掃描。

07、鳴謝

好了,各位讀者朋友們,答應小王的文章終於寫完了。能看到這裏的都是最優秀的程序員,升職加薪就是你了。如果覺得不過癮,還想看到更多,可以 star 二哥的 GitHub【itwanger.github.io】,本文已收錄。

PS:本文配套的源碼已上傳至 GitHub 【SpringBootDemo.SpringBootMysql】。

原創不易,如果覺得有點用的話,請不要吝嗇你手中點贊的權力;如果想要第一時間看到二哥更新的文章,請掃描下方的二維碼,關注沉默王二公眾號。我們下篇文章見!

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

【其他文章推薦】

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

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

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

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

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

WebGPU+光線追蹤Ray Tracing 開發三個月總結

大家好~這三個月以來,我一直在學習和實現“基於WebGPU的混合光線追蹤實時渲染”的技術,使用了Ray Tracing管線(如.rgen、.rmiss等着色器)。
現在與大家分享和介紹我目前的學習成果,希望對大家有所幫助!謝謝!

通過國外的開源項目,可在WebGPU中使用Ray Tracing管線

這三個月我對Ray Tracing的研究有了質的突破,主要歸功於我發現的WebGPU Node開源項目!
該作者首先在dawn-ray-tracing開源項目中對“dawn項目:Chrome對WebGPU的實現”進行了擴展,加入了光追的API;
然後在WebGPU Node開源項目中,底層封裝了Vulkan SDK,上層使用了dawn-ray-tracing項目,提供了WebGPU API,實現了在Nodejs環境中使用WebGPU API和Ray Tracing管線來實現硬件加速的光線追蹤(電腦需要使用nvdia的RTX顯卡)!

相關介紹參見:
Real-Time Ray-Tracing in WebGPU

搭建運行環境

有兩種方法來搭建運行環境:
1、給Chrome瀏覽器打補丁,使其與下載DXR驅動(DirectX Raytracing)關聯,從而在該瀏覽器中運行
詳見該作者最近寫的開源項目:chromium-ray-tracing
(我沒有測試過,不知道是否能使用)

2、編譯dawn-ray-tracing和WebGPU Node項目,從而在Nodejs環境中運行
我使用的是這個方法(不過我使用的WebGPU Node項目是今年3月份時的代碼,最新的代碼我還沒有編譯成功)。

我的操作系統是win7,顯卡是RTX 2060s,vulkan sdk是1.1.126.0版本

/* 最新代碼我還沒有編譯成功哈哈!請先不要進行下面的編譯操作!

編譯的步驟為(需要使用VPN翻牆):

# 編譯dawn-ray-tracing項目

## Clone the repo as "dawn-ray-tracing"
git clone https://github.com/maierfelix/dawn-ray-tracing

cd dawn-ray-tracing

## Bootstrap the gclient configuration
cp scripts/standalone.gclient .gclient

## Fetch external dependencies and toolchains with gclient
gclient sync


set DEPOT_TOOLS_WIN_TOOLCHAIN=0

npm install --global --production windows-build-tools

gn gen out/Shared --ide=vs --target_cpu="x64" --args="is_component_build=true is_debug=false is_clang=false"

ninja -C out/Shared


# 編譯webgpu node項目

npm install webgpu

在webgpu node的根目錄中創建名為“PATH_TO_DAWN”的文件,在其中指定dawn-ray-tracing項目的絕對路徑,如:
D:/Github/dawn-ray-tracing

在webgpu node的根目錄中執行:
npm run all --dawnversion=0.0.1
(
這裏要注意的是,需要先安裝Vulkan SDK和python;

可以通過“npm config set python C:\depot_tools\python.bat”來設置python路徑,或者指定python路徑:
npm run all --dawnversion=0.0.1 --python="C:\Users\Administrator\Downloads\depot_tools\bootstrap-3_8_0_chromium_8_bin\python\bin\python.exe"
)


# 在nodejs中運行ray tracing示例,驗證是否成功

進入webgpu node的根目錄

cd examples & cd ..
node --experimental-modules examples/ray-tracing/index.mjs

*/

應用場景

考慮到WebGPU還沒有正式發布,並且可能在三年內瀏覽器都不會支持Ray Tracing管線,所以我把渲染放到雲端,這樣就可以在雲端自行搭建環境(如使用WebGPU Node開源項目),然後通過網絡傳輸將渲染結果傳輸到客戶端,從而在客戶端瀏覽器不支持的情況下仍能显示光追渲染的畫面。

因此,我的應用場景為:
1、雲渲染
2、雲遊戲

這兩個應用場景有不同的需求:
“雲渲染”屬於離線渲染,我們關心的是:

  • 畫質要好
  • 渲染時間可以長點

因此:

  • 每幀可採樣多次,即n spp(n >= 30)
  • 支持多種渲染效果,如“焦射”(causicts)等
  • 全局光照可使用n次bounce(n >= 2)

“雲遊戲”屬於實時渲染,我們關心的是:

  • 畫質可以差點
  • 渲染時間要短(每幀30ms以內)

因此:

  • 每幀只採樣一次,即1 spp
  • 全局光照只使用一次或兩次bounce
  • 對“焦射”(causicts)等場景用性能好的方案達到接近的渲染效果,通過犧牲畫質來減少渲染時間

介紹我目前的實現方案

主要技術框架是“實時混合光線追蹤”,主要包含下面的pass:
1、gbuffer pass
創建gbuffer
2、ray tracing pass
直接從gbuffer中獲取world position、diffuse等數據,用來計算直接光照,從而減少了每個像素髮射的光線數量;
每個像素髮射1個shadow ray,用來計算直接光照的陰影;
如果只用1個bounce來計算全局光照的話,每個像素髮射1個indirect ray+1個shadow ray,用來計算間接光照。
3、denoise pass
基於BMFR算法來實現降噪,具體可參考本文後面的“實現降噪Denoise”部分。
4、taa pass
使用taa來抗鋸齒

相關代碼可見我的開源項目:
WebGPU-RTX

介紹我學習的整個流程,分享相關資料

了解光線追蹤的相關領域

我通過下面的文章進行了初步的了解:
一篇光線追蹤的入門
光線追蹤與實時渲染的未來
實時光線追蹤技術:業界發展近況與未來挑戰
Introduction to NVIDIA RTX and DirectX Ray Tracing
如何評價微軟的 DXR(DirectX Raytracing)?

實現第一個光追的Demo

通過學習下面的資料:
Ray Tracing in One Weekend
Ray Tracing: The Next Week
Ray Tracing in One Weekend和Ray Tracing: The Next Week的詳解
基於OpenGL的GPU光線追蹤

我參考資料中的代碼,用WebGL 2實現一個Demo:

該場景的紅圈中是一個球,附近有一個球形光源和一個矩形光源

因為沒有進行降噪,所以噪點太多了哈哈!

相關代碼可見我的開源項目:
Wonder-RayTrace

學習和實現Ray Tracing管線

通過學習NVIDIA Vulkan Ray Tracing Tutorial教程,我用 js語言+WebGPU Node開源項目 基於Ray Tracing管線依次實現了陰影、反射等基礎渲染效果。

該教程使用了VK_KHR_ray_tracing擴展,而WebGPU Node開源項目也使用了該擴展(Vulkan SDK),因此該教程的shader代碼幾乎可以直接用到該開源項目中。

教程代碼

用Reason重寫

我用Reason語言重寫了示例代碼,提煉了一個基礎架構。

學習GBuffer+Ray Tracing混合管線

因為我希望優先減少渲染時間,所以我要通過混合管線來進行實時渲染。

我通過A Gentle Introduction To DirectX Raytracing教程來學習和實現。

教程代碼下載

我學習了該教程的第一篇到第11篇,分別實現了創建GBuffer、使用Lambertian材質渲染、多光源的陰影等內容。

實現降噪Denoise

教程的第9篇通過每個像素對每個光源發射一個shadow ray,最後累加並計算平均值,實現了多光源的陰影。

教程的第11篇對第9篇進行了改進:為了減少每個像素髮射的shadow ray的數量,每個像素只隨機向一個光源發射一個shadow ray。
這樣會導致噪點,如下圖所示:

我們可以通過累計採樣數來不斷逼近無噪點的圖片(如該教程的第6篇一樣),但這樣需要經過長時間后才會收斂,所以只適合“雲渲染”這種離線渲染的應用場景。

累加一定幀數后,結果如下圖所示:

實現taa

降噪算法通常需要先實現“幀間的數據復用”,而TAA抗鋸齒也需要實現“幀間數據復用”的技術;而且降噪算法會使用TAA作為最後一個pass來抗鋸齒。所以我決定先實現taa,將其作為實現降噪算法的鋪墊。

我參考了下面的資料來實現taa:
DX12渲染管線(2) – 時間性抗鋸齒(TAA)、 相關代碼
Unity Temporal AA的改進與提高、 相關代碼
unit Temporal Anti-Aliasing

實現BMFR降噪算法

為了能應用於“雲遊戲”這種實時渲染的應用場景,我們需要快速降噪。因此我實現了BMFR算法來降噪。

降噪前場景:

降噪后場景:

我參考了下面的資料:
BLOCKWISE MULTI-ORDER FEATURE REGRESSION FOR REAL-TIME PATH TRACING RECONSTRUCTION
參考代碼

學習蒙特卡羅積分(monte carlo)的理論

教程的第11篇隨機向一個光源發射一個shadow ray,這其實已經使用了蒙特卡羅積分的理論。

我們可以通過下面的資料深入學習該理論,了解概率密度函數(pdf)、重要性採樣等相關概念,為我們後面實現全局光照打下理論基礎:
【RAY TRACING THE REST OF YOUR LIFE 超詳解】 光線追蹤 3-1 蒙特卡羅 (一) 到 【RAY TRACING THE REST OF YOUR LIFE 超詳解】 光線追蹤 3-7 混合概率密
光線追蹤器Ray Tracer:進階篇

實現全局光照

通過學習教程的第12篇,我實現了one bounce的全局光照。

更多參考資料:
Global Illumination and Path Tracing
Global Illumination and Monte Carlo

這裏我遇到的問題主要是處理indirect specular noise:噪點不穩定,導致降噪后不穩定(高光周圍有明顯波動)。
我首先以為是pdf寫錯了,結果修改了pdf后還是沒有改進;
然後希望通過clamp等方法移除這些高光的fireflies噪點,結果影響到了畫質;
最後採用了“採樣indirect specular/diffuse多次”來穩定噪點。這適用於“雲渲染”的離線渲染,但不適用於“雲遊戲”的實時渲染。

基於GGX模型,實現disney BRDF

通過學習教程的第14篇,我引入了pbr材質,實現了GGX模型,加入了多bounce的全局光照。

我對教程代碼進行了改進:
在.rgen着色器中使用for循環而不是遞歸來實現的多bounce;
實現了disney BRDF,在pbr材質中有diffuse、roughness、metallic、specular這幾個參數。

更多參考資料:
基於物理着色(二)- Microfacet材質和多層材質
基於物理着色(三)- Disney和UE4的實現
基於物理的渲染(PBR)白皮書 | 迪士尼原則的BRDF與BSDF相關總結
WebGPU-Path-Tracer 實現了disney BRDF

目前的渲染效果

我目前的實現需要改進的地方

在Ray Tracing pass中支持紋理

使用bindless texture或者virtual texture來實現

擴展disney BRDF,實現BSDF,支持透明、折射效果

增加后處理

如gamma矯正等

在雲端環境下多線程渲染

雲端天然具有并行的優勢,因此可將渲染任務分配到多個顯卡/服務器中執行。

改進降噪效果

BMFR對高光specular處理得不好。
為了應用在“雲渲染”中,需要提高畫質。因此可考慮:

  • 改進BMFR對specular的處理
    BMFR論文中已有相關的討論
  • 使用專門對多個spp採樣進行降噪的降噪器來替代BMFR
    因為BMFR主要是針對1 spp採樣,所以需要使用針對蒙托卡羅積分路徑追蹤的降噪器來替代

改進indirect specular/diffuse noise

現在我通過增加spp來增加噪點的穩定性,這在“雲遊戲”中行不通,因為只能有1 spp。因此可考慮:

  • 使用blue noise
    可參考: http://psgraphics.blogspot.com/2018/10/flavors-of-sampling-in-ray-tracing.html
    https://hal.archives-ouvertes.fr/hal-02158423/file/blueNoiseTemporal2019_slides.pdf
    https://belcour.github.io/blog/research/2019/06/18/animation-bluenoise.html
    https://zhuanlan.zhihu.com/p/90017623
  • 對GGX模型使用VNDF來代替NDF採樣
  • 對多bounce的indirect specular noise進行優化
    可能的解決方案:
    使用reflection denoise filter;
    adaptive multiple bounce;
  • 使用photon mapping來降低噪點

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

【其他文章推薦】

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

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

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

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

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

水上太陽能火災 消防車要用特別款──千葉・山倉風災事件啟示錄

文:宋瑞文(加州能源特約撰述)

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

【其他文章推薦】

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

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

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

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

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