標籤: 台北網頁設計

  • Dev 日誌 | 一次 Segmentation Fault 和 GCC Illegal Instruction 編譯問題排查

    Dev 日誌 | 一次 Segmentation Fault 和 GCC Illegal Instruction 編譯問題排查

    摘要

    筆者最近在重新整理和編譯 Nebula Graph 的第三方依賴,選出兩個比較有意思的問題給大家分享一下。

    Flex Segmentation Fault——Segmentation fault (core dumped)

    在編譯 Flex 過程中,遇到了 Segmentation fault:

    make[2]: Entering directory '/home/dutor/flex-2.6.4/src'
    ./stage1flex   -o stage1scan.c ./scan.l
    make[2]: *** [Makefile:1696: stage1scan.c] Segmentation fault (core dumped)

    使用 gdb 查看 coredump:

    Core was generated by `./stage1flex -o stage1scan.c ./scan.l'.
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0  flexinit (argc=4, argv=0x7ffd25bea718) at main.c:976
    976             action_array[0] = '\0';
    (gdb) disas
    Dump of assembler code for function flexinit:
       0x0000556c1b1ae040 <+0>:     push   %r15
       0x0000556c1b1ae042 <+2>:     lea    0x140fd(%rip),%rax        # 0x556c1b1c2146
       ...
       0x0000556c1b1ae20f <+463>:   callq  0x556c1b1af460 <allocate_array> #這裏申請了buffer
       ...
    => 0x0000556c1b1ae24f <+527>:   movb   $0x0,(%rax) # 這裏向buffer[0]寫入一個字節,地址非法,掛掉了
       ...
    (gdb) disas allocate_array
    Dump of assembler code for function allocate_array:
       0x0000556c1b1af460 <+0>:     sub    $0x8,%rsp
       0x0000556c1b1af464 <+4>:     mov    %rsi,%rdx
       0x0000556c1b1af467 <+7>:     xor    %eax,%eax
       0x0000556c1b1af469 <+9>:     movslq %edi,%rsi
       0x0000556c1b1af46c <+12>:    xor    %edi,%edi
       0x0000556c1b1af46e <+14>:    callq  0x556c1b19a100 <reallocarray@plt> # 調用庫函數申請內存
       0x0000556c1b1af473 <+19>:    test   %eax,%eax # 判斷是否為 NULL
       0x0000556c1b1af475 <+21>:    je     0x556c1b1af47e <allocate_array+30># 跳轉至NULL錯誤處理
       0x0000556c1b1af477 <+23>:    cltq   # 將 eax 符號擴展至 rax,造成截斷
       0x0000556c1b1af479 <+25>:    add    $0x8,%rsp
       0x0000556c1b1af47d <+29>:    retq
       ...
    End of assembler dump.

    可以看到,問題出在了 allocate_array 函數。因為 reallocarray 返回指針,返回值應該使用 64 bit 寄存器rax,但 allocate_array 調用 reallocarray 之後,檢查的卻是 32 bit 的 eax,同時使用 cltq 指令將 eax 符號擴展 到 rax。原因只有一個:allocate_array 看到的 reallocarray 的原型,與 reallocarry 的實際定義不符。翻看編譯日誌,確實找到了 implicit declaration of function ‘reallocarray’ 相關的警告。configure 階段添加 CFLAGS=-D_GNU_SOURCE 即可解決此問題。

    注:此問題不是必現,但編譯/鏈接選項 -pie 和 內核參數 kernel.randomize_va_space 有助於復現。

    總結:

    • 隱式聲明的函數在 C 中,返回值被認為是 int
    • 關注編譯器告警,-Wall -Wextra 要打開,開發模式下最好打開 -Werror。

    GCC Illegal Instruction——internal compiler error: Illegal instruction

    前陣子,接到用戶反饋,在編譯 Nebula Graph 過程中遭遇了編譯器非法指令的錯誤,詳見(#978)[]

    錯誤信息大概是這樣的:

    Scanning dependencies of target base_obj_gch
    [ 0%] Generating Base.h.gch
    In file included from /opt/nebula/gcc/include/c++/8.2.0/chrono:40,
    from /opt/nebula/gcc/include/c++/8.2.0/thread:38,
    from /home/zkzy/nebula/nebula/src/common/base/Base.h:15:
    /opt/nebula/gcc/include/c++/8.2.0/limits:1599:7: internal compiler error: Illegal instruction
    min() _GLIBCXX_USE_NOEXCEPT { return FLT_MIN; }
    ^~~
    0xb48c5f crash_signal
    ../.././gcc/toplev.c:325
    Please submit a full bug report,
    with preprocessed source if appropriate.

    既然是 internal compiler error,想必是 g++ 本身使用了非法指令。為了定位具體的非法指令集及其所屬模塊,我們需要復現這個問題。幸運的是,下面的代碼片段就能觸發:

    #include <thread>
    int main() 
    {
        return 0;
    }

    非法指令一定會觸發 SIGILL,又因為 g++ 只是編譯器的入口,真正幹活的是 cc1plus。我們可以使用 gdb 來運行編譯命令,抓住子進程使用非法指令的第一現場:

    $ gdb --args /opt/nebula/gcc/bin/g++ test.cpp
    gdb> set follow-fork-mode child
    gdb> run
    Starting program: /opt/nebula/gcc/bin/g++ test.cpp
    [New process 31172]
    process 31172 is executing new program: /opt/nebula/gcc/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1plus
    Thread 2.1 "cc1plus" received signal SIGILL, Illegal instruction.
    [Switching to process 31172]
    0x00000000013aa0fb in __gmpn_mul_1 ()
    gdb> disas
    ...
    0x00000000013aa086 <+38>: mulx (%rsi),%r10,%r8
    ...

    Bingo!mulx 屬於 BMI2 指令集,報錯機器 CPU 不支持該指令集。
    仔細調查,引入該指令集的是 GCC 的依賴之一,GMP。默認情況下,GMP 會在 configure 階段探測當前機器的 CPU 具體類型,以期最大化利用 CPU 的擴展指令集,提升性能,但卻犧牲了二進制的可移植性。解決方法是,configure 之前,使用代碼目錄中的 configfsf.guess configfsf.sub 替換或者覆蓋默認的 config.guess 和 config.sub

    總結:

    • 某些依賴可能因為性能或者配置的原因,造成二進制的不兼容。
    • 缺省參數下,GCC 為了兼容性,不會使用較新的指令集。
    • 為了平衡兼容性和性能,你需要做一些額外的工作,比如像 glibc 那樣在運行時選擇和綁定某個具體實現。

    最後,如果你想嘗試編譯一下 Nebula 源代碼可參考以下方式:

    bash> git clone https://github.com/vesoft-inc/nebula.git
    bash> cd nebula && ./build_dep.sh N

    有問題請在 GitHub 或者微信公眾號上留言。

    附錄

    • Nebula Graph:一個開源的分佈式圖數據庫
    • GitHub:
    • 知乎:
    • 微博:

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

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

    小三通物流營運型態?

    ※快速運回,大陸空運推薦?

  • Appium+python自動化(四十一)-Appium自動化測試框架綜合實踐 – 即將落下帷幕(超詳解)

    Appium+python自動化(四十一)-Appium自動化測試框架綜合實踐 – 即將落下帷幕(超詳解)

    1.簡介

      今天我們緊接着上一篇繼續分享Appium自動化測試框架綜合實踐 – 代碼實現。到今天為止,大功即將告成;框架所需要的代碼實現都基本完成。

    2.data數據封裝

    2.1使用背景

    在實際項目過程中,我們的數據可能是存儲在一個數據文件中,如txt,excel、csv文件類型。我們可以封裝一些方法來讀取文件中的數據來實現數據驅動。

    2.2案例

    將測試賬號存儲在account.csv文件,內容如下:

    account.csv

    hg2018

    hg2018

    hg2019

    zxw2019

    666

    222

    參考代碼

    2.3enumerate()簡介

    enumerate()是python的內置函數

    • enumerate在字典上是枚舉、列舉的意思
    • 對於一個可迭代的(iterable)/可遍歷的對象(如列表、字符串),enumerate將其組成一個索引序列,利用它可以同時獲得索引和值
    • enumerate多用於在for循環中得到計數。

    2.4enumerate()使用

    如果對一個列表,既要遍歷索引又要遍曆元素時,首先可以這樣寫:

    參考代碼
    list = ["", "", "一個", "測試","數據"]
    
    for i in range(len(list)):
    
        print(i,list[i])

    上述方法有些累贅,利用enumerate()會更加直接和優美:

    參考代碼
    list1 = ["", "", "一個", "測試","數據"]
    
    for index, item in enumerate(list1):
    
            print(index,item)

    3.數據讀取方法封裝

      數據讀取方法也屬於公共方法,這裏我們首先實現一下,然後將其封裝到裡邊即可。

    3.1數據讀取方法實現的參考代碼

    import csv
    
    
         def get_csv_data(csv_file,line):
    
            with open(csv_file, 'r', encoding='utf-8-sig') as file:
    
                reader=csv.reader(file)
    
                for index, row in enumerate(reader,1):
    
                    if index == line:
    
                        return row
    
     
    
        csv_file='../data/account.csv'
    
        data=get_csv_data(csv_file,3)
    
        print(data)

    3.2封裝

    將其封裝在公共方法中,在其他地方用到的時候,直接導入調用即可。

    4.utf-8與utf-8-sig兩種編碼格式的區別

    UTF-8以字節為編碼單元,它的字節順序在所有系統中都是一樣的,沒有字節序的問題,也因此它實際上並不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。

    5.config文件配置

    各種配置文件都放在這個目錄下。

    5.1日誌文件配置 

    主要是一些日誌信息的配置。

    log.config

     參考代碼
    [loggers]
    keys=root,infoLogger
    
    [logger_root]
    level=DEBUG
    handlers=consoleHandler,fileHandler
    
    [logger_infoLogger]
    handlers=consoleHandler,fileHandler
    qualname=infoLogger
    propagate=0
    
    [handlers]
    keys=consoleHandler,fileHandler
    
    [handler_consoleHandler]
    class=StreamHandler
    level=INFO
    formatter=form02
    args=(sys.stdout,)
    
    [handler_fileHandler]
    class=FileHandler
    level=INFO
    formatter=form01
    args=('../logs/runlog.log', 'a')
    
    [formatters]
    keys=form01,form02
    
    [formatter_form01]
    format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
    
    [formatter_form02]
    format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

    6.測試用例封裝

    這裏宏哥舉例給小夥伴們演示:封裝註冊和登錄兩個測試用例。

    6.1測試用例執行開始結束操作封裝

    測試用例執行開始和結束的封裝,其他模塊用到直接導入,調用即可。

    myunit.py

    參考代碼
    # coding=utf-8
    # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行
    
    # 2.註釋:包括記錄創建時間,創建人,項目名稱。
    '''
    Created on 2019-11-20
    @author: 北京-宏哥   QQ交流群:707699217
    Project:Appium自動化測試框架綜合實踐 - 代碼實現
    '''
    # 3.導入模塊
    import unittest
    from kyb_testProject.common.desired_caps import appium_desired
    import logging
    from time import sleep
    
    class StartEnd(unittest.TestCase):
        def setUp(self):
            logging.info('=====setUp====')
            self.driver=appium_desired()
    
        def tearDown(self):
            logging.info('====tearDown====')
            sleep(5)
            self.driver.close_app()

    6.2註冊用例

    開始註冊用例代碼邏輯的實現。

    test_register.py

    參考代碼
    # coding=utf-8
    # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行
    
    # 2.註釋:包括記錄創建時間,創建人,項目名稱。
    '''
    Created on 2019-11-20
    @author: 北京-宏哥   QQ交流群:707699217
    Project:Appium自動化測試框架綜合實踐 - 代碼實現
    '''
    # 3.導入模塊
    from kyb_testProject.common.myunit import StartEnd
    from kyb_testProject.businessView.registerView import RegisterView
    import logging,random,unittest
    
    class RegisterTest(StartEnd):
        def test_user_register(self):
            logging.info('======test_user_register======')
            r=RegisterView(self.driver)
    
            username = 'bjhg2019' + 'fly' + str(random.randint(1000, 9000))
            password = 'bjhg2020' + str(random.randint(1000, 9000))
            email = 'bjhg' + str(random.randint(1000, 9000)) + '@163.com'
    
            self.assertTrue(r.register_action(username,password,email))
    
    if __name__ == '__main__':
        unittest.main()

    6.3登錄用例

    開始登錄用例代碼邏輯的實現。

    test_login.py

    參考代碼
    # coding=utf-8
    # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行
    
    # 2.註釋:包括記錄創建時間,創建人,項目名稱。
    '''
    Created on 2019-11-13
    @author: 北京-宏哥   QQ交流群:707699217
    Project:Appium自動化測試框架綜合實踐 - 代碼實現
    '''
    # 3.導入模塊
    from kyb_testProject.common.myunit import StartEnd
    from kyb_testProject.businessView.loginView import LoginView
    import unittest
    import logging
    
    class TestLogin(StartEnd):
        csv_file='../data/account.csv'
    
        @unittest.skip('test_login_zxw2018')
        def test_login_zxw2018(self):
            logging.info('======test_login_zxw2018=====')
            l=LoginView(self.driver)
            data=l.get_csv_data(self.csv_file,2)
    
            l.login_action(data[0],data[1])
            self.assertTrue(l.check_loginStatus())
    
        # @unittest.skip('skip test_login_zxw2017')
        def test_login_zxw2017(self):
            logging.info('======test_login_zxw2017=====')
            l=LoginView(self.driver)
            data = l.get_csv_data(self.csv_file, 1)
    
            l.login_action(data[0], data[1])
            self.assertTrue(l.check_loginStatus())
    
        @unittest.skip('test_login_error')
        def test_login_error(self):
            logging.info('======test_login_error=====')
            l = LoginView(self.driver)
            data = l.get_csv_data(self.csv_file, 3)
    
            l.login_action(data[0], data[1])
            self.assertTrue(l.check_loginStatus(),msg='login fail!')
    
    if __name__ == '__main__':
        unittest.main()

    7.小結

    到此,Appium自動化測試框架就差下一篇就全部完成了,聰明的你都懂了嗎???嘿嘿!慢慢地來吧。

    下節預告

    下一篇,講解執行測試用例,生成測試報告,以及自動化平台,請關注宏哥,敬請期待!!!

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

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • Thrift總結(四)Thrift實現雙向通信

    Thrift總結(四)Thrift實現雙向通信

    前面介紹過 Thrift 安裝和使用,介紹了Thrift服務的發布和客戶端調用,可以查看我之前的文章:

    但是,之前介紹的都是單向的客戶端發送消息,服務端接收消息。而客戶端卻得不到服務器的響應。

    那如果我們要實現雙向通信(即:客戶端發送請求,服務端處理返回,服務端發送消息,客戶端處理返回)的功能,該怎麼實現呢?

     

    其實在不涉及語言平台的制約,WebService或是webapi 就可以實現這種客戶端發起請求,服務端的處理的單向流程。

    然而,實際場景中,可能我們的某些業務需求,更需要服務端能夠響應請求並處理數據。下面我通過一個demo案例,介紹下Thrift 是如何實現雙向通信的。

     

    一、安裝Thrift

    這裏不再贅述,戳這裏查看我上篇文章的介紹:

     

    二、編寫Thrift IDL文件 

    編寫thrift腳本,命名為student.thrift  如下:

    service HelloWorldService{
        void SayHello(1:string msg);
    }

    生成service 的方法,之前的文章有介紹,這裏就不介紹了。

     

    三、編寫服務端代碼

    創建HelloThrift.Server 服務端工程,添加HelloWorldBidirectionServer類,HelloWorldBidirectionServer 實現了Iface接口用於接收客戶端消息,並有一個客戶端傳輸層對象集合用於記錄所有已連接的客戶端。

     public class HelloWorldBidirectionServer : HelloWorldBidirectionService.Iface
        {
            public void Run(int port)
            {
                try
                {
                    TServerTransport transport = new TServerSocket(port);
    
                    TTransportFactory transportFac = new TTransportFactory();
    
                    TProtocolFactory inputProtocolFactory = new TBinaryProtocol.Factory();
                    TThreadPoolServer server = new TThreadPoolServer(getProcessorFactory(), transport, transportFac, inputProtocolFactory);
    
                    server.Serve();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            public static List<TTransport> TransportCollection = new List<TTransport>();
    
            public void SayHello(string msg)
            {
                Console.WriteLine(string.Format("{0:yyyy/MM/dd hh:mm:ss} 服務端接收到消息: {1}", DateTime.Now, msg));
            }
    
            public void SayToClient(string msg)
            {
                try
                {
                    foreach (TTransport trans in TransportCollection)
                    {
                        TBinaryProtocol protocol = new TBinaryProtocol(trans);
                        HelloWorldBidirectionService.Client client = new HelloWorldBidirectionService.Client(protocol);
                        //Thread.Sleep(1000);
                        client.SayHello(msg);
                        //Console.WriteLine("發給了客戶端喲");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            public TProcessorFactory getProcessorFactory()
            {
                return new HelloWorldBidirectionProcessor();
            }
        }
    
        public class HelloWorldBidirectionProcessor : TProcessorFactory
        {
            public TProcessor GetProcessor(TTransport trans, TServer server = null)
            {
                if (trans.IsOpen)
                {
                    HelloWorldBidirectionServer.TransportCollection.Add(trans);
                    Console.WriteLine("客戶端連上。");
                }
    
                HelloWorldBidirectionServer srv = new HelloWorldBidirectionServer();
                return new global::HelloWorldBidirectionService.Processor(srv);
            }
        }

     

    四、編寫客戶端代碼

    首先創建HelloThrift.Client客戶端項目,添加接收服務端消息的類HelloWorldBidirectionClient,裏面只有一個實現Iface接口的方法:

      public class HelloWorldBidirectionClient
        {
            static HelloWorldBidirectionService.Client client = null;
            public void ConnectAndListern(int port, string ip = "127.0.0.1")
            {
                //Tsocket: TCP/IP Socket接口
                TSocket tSocket = new TSocket(ip, port);
                //消息結構協議
                TProtocol protocol = new TBinaryProtocol(tSocket);
                try
                {
                    if (client == null)
                    {
                        client = new global::HelloWorldBidirectionService.Client(protocol);
                        tSocket.Open();//建立連接
                        StartListern(tSocket);//啟動監聽線程
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            public void Say(string msg)
            {
                if (client != null)
                    client.SayHello(msg);
            }
    
            void StartListern(TSocket tSocket)
            {
                Thread t = new Thread(new ParameterizedThreadStart(Run));
                t.Start(tSocket);
            }
    
            public void Run(object tSocket)
            {
                HelloWorldBidirectionService.Processor process = new HelloWorldBidirectionService.Processor(new HelloWorldBidirectionFace());
    
                try
                {
                    while (process.Process(new TBinaryProtocol((TSocket)tSocket), new TBinaryProtocol((TSocket)tSocket)))
                    {
                        Console.WriteLine("消息接收完成,等下一波,阻塞中......");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("連接斷開..." + ex.Message);
                }
            }
    
        }
        class HelloWorldBidirectionFace : HelloWorldBidirectionService.Iface
        {
            public void SayHello(string msg)
            {
                Console.WriteLine(string.Format("{0:yyyy/MM/dd hh:mm:ss} 收到服務端響應消息 {1}", DateTime.Now, msg));
    
            }
        }

     實現客戶端,ConnectAndListern方法可以與服務端建立連接,並開啟客戶端端口監聽來自服務端的信息。Say方法可將消息發送至服務端。

     

    五、測試

     測試效果如下:

     

     

     

    六、最後

      1. 關於使用Thrift 構建我們自己的rpc 的方法,這裏基本講完了。其他的方法本文就不再演示了,調用起來都是一樣。  

      2. 後續會簡單討論一下Thrift 框架的通信原理。

      3. 源代碼下載,

     

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

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包”嚨底家”

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

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

    小三通海運與一般國際貿易有何不同?

    小三通快遞通關作業有哪些?

  • 北極白鯨驚奇現身泰晤士河 再不回家專家憂安危

    摘錄自2018年9月26日中央社報導

    據英國各大媒體報導,一隻迷途的白鯨現身英國泰晤士河,第一次被目擊是25日在肯特郡(Kent)格雷夫森德(Gravesend)的泰晤士河段,當時白鯨正在駁船附近覓食,被暱稱為「班尼」(Benny),距離其原棲息地北極圈水域達數千公里。26日白鯨再次現身同個地點,引發是否迷航及可能遇險的擔憂。

    鯨豚保育協會(WDC)海洋哺乳類動物科學家羅特(Rob Lott)表示,這隻白鯨正受到監控,以防牠擱淺。「但白鯨停留在泰晤士河口的時間愈長,就愈令人擔心。」

    海洋生物保育慈善團體ORCA的保育學家巴比(Lucy Babey)表示:「這是白鯨出現在英國的最南端紀錄。」

    英國海洋生物救援組織表示,英國最後一次發現白鯨蹤跡是3年前在北英格蘭的諾森伯蘭(Northumberland)海岸,以及北愛爾蘭,但極為罕見。

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 保護環境 越南明年起加徵汽油環保稅

    摘錄自2018年9月21日中央社報導

    為了保護和改善環境,越南政府自明年起將調漲對汽油等燃料產品的環境保護稅,其中汽油每公升環保稅將從現行收費3000越盾(約新台幣4元)提升為4000越盾。

    越南國會常務委員會昨天(20日)通過有關環境保護稅的決議,自明年起將對相關產品加徵環保稅,希望藉此保護與改善環境,減少污染物排放。

    根據這項決議,汽油每公升環保稅將從現行收費3000越盾提升為4000越盾,柴油從1500越盾升到2000越盾,燃油和潤滑油從900越盾升到2000越盾等;此外,煤炭、塑膠袋與除草劑等也被列入加徵環保稅的產品名單。

    越南國會官員指出,加徵對汽油等燃料產品的環保稅後,國家預算每年將增加15.7兆越盾,這是一筆很大的稅收,有利用於保護與改善環境。

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

    【其他文章推薦】

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

    小三通物流營運型態?

    ※快速運回,大陸空運推薦?

  • 中國新能源汽車零部件發展規劃成果集中亮相北京10月車展

    中國新能源汽車零部件發展規劃成果集中亮相北京10月車展

    2016年10月13—16日,以“選擇·行動——未來從現在開始”為主題的2016(第四屆)節能與新能源汽車產業發展規 劃成果展覽會、中國國際汽車新能源及技術應用展覽會將在北京國家會議中心舉辦。展會由中國國家工業和資訊化部支援,科學技術部、中國國際貿易促進委員會批准,是貫徹落實國務院《節能與 新能源汽車產業發展規劃(2012—2020年)》,推動中國節能與新能源汽車產業發展的重要舉措之一。本屆展會將全方面覆蓋節能環保汽車、純電動 汽車、混合動力汽車、插電式混合動力和燃料電池汽車,以及電池、電機、電控等關鍵零部件和充電設施等產品,眾多國際知名汽車企業、零部件和充電設施供應 商將攜旗下新品參展。

    汽車產業是國民經濟的重要支柱產業,也是實現新一輪技術革命和產業變革的重要載體。中國汽車產業快速發展,產銷增速連續七年居世界第一位,新能源汽車產業初具規模,15年中國已成為全球最大的新能源汽車生產以及銷售市場.

    但同時,據中國國家863“節能與新能源汽車”重大項目監理諮詢專家組王秉剛調研,中國目前具有生產傳統汽車ABS系統能力的工廠主要有亞太、元豐與伯特利等幾家,他們是未來最有希望成為中國自主電動汽車制動系統的生產企業,與國外同類企業相比,他們規模都不大,在同類產品的市場佔有率不足5%,在年產量達2000多萬輛的中國汽車產業裡,如此重要的底盤部件,自主企業生產的比例低到差不多可以忽略不計的程度。中國汽車產業空心化可見一斑!這裡舉的僅是制動系統的例子,其它零部件也存在類似情況,就連備受關注的動力電池也未必樂觀,已經有國外大電池企業,在部分地方政府優惠政策的支援下在國內建廠。

    中國新能源汽車零部件企業正加強關鍵核心技術研發,推進技術創新,竭盡全力避免傳統汽車產業存在的核心技術缺失、產業空心化現象,在新能源汽車行業重蹈覆轍。據車展合作單位盛大超越展覽公司嶽巍介紹,“新能源汽車零部件主要包括電機、驅動控制系統和電源系統,目前中國在新能源汽車零部件上的技術創新有序推進,整體研發水平不斷提升,中國企業的電機及驅動控制系統在新能源客車(如宇通、安凱、中通等)及乘用車(比亞迪、北汽、江淮等)上已得到廣泛應用,這些成果大部分將在北京10月新能源汽車展上展出,中國的電機及驅動控制系統參展企業包括:德沃仕、英威騰、中冶南方、超同步、合普動力、合康動力、福工動力、八達等。這些企業有的具有國外及科研院所的專業背景,有的是從電梯控制、機床控制發展而來。比如合普動力是低速電動車電機驅動控制的領軍企業,隨著高速新能源汽車市場的不斷成長,已開發了電動客車及乘用車電機驅動控制產品”。

    盛大超越展覽公司電池及BMS展區經理耿忱也對中國企業抱有積極信心,他說,”北京10月新能源汽車成果展上的中國電池企業非常給力,沃特瑪、寧德時代、中航鋰電、力神電池、比克電池、萬向、山東威能、神工光電、內蒙古稀奧科、實聯長宜等知名電池企業展示了車用動力電池技術及市場應用的發展成果,部分電池展商還帶來了實際應用整車配合展示”。他還表示,“環宇賽爾、科隆集團、均勝普瑞等一批新的中國電池及BMS展商將有望加盟2016北京10月新能源汽車成果展,給主機廠提供更加前沿和多元化的產品解決方案“。

    展會相關

    2016中國國際汽車新能源及技術應用展覽會
    節能與新能源汽車產業發展規劃成果展覽會
    行業地位:中國最大高速新能源汽車展
    展覽規模:30,000平方米(2015年)
    觀眾數量:60,000人次(2015年)
    展覽週期:每年一屆,2013年首屆
    連絡人:岳巍 先生
    手機:+86 135 5286 5285
    展會網址:
     

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 呼和浩特總投資200億元新能源汽車項目正式開工

    日前,計畫總投資約200億元的內蒙古自治區呼和浩特市金山高新區新能源汽車製造專案舉行了集中開工儀式。

    該項目占地2605畝、計畫總投資約200億元,其中基礎設施、廠房投資35億元,設計建築面積102.7萬平方米,擬入駐規模以上工業企業20家以上。項目建成後,年產值預計可達500億元,提供就業崗位3萬個,將成為內蒙古新能源汽車及核心零部件產業聚集區。

    該專案採取PPP建設模式,分三期推進。目前集中開工的6個專案是首期落戶的項目,計畫於2017年1月實現部分產能投產,預計當年產值可達100億元左右,提供就業崗位6千餘個。

    呼和浩特市金山高新區新能源汽車製造專案是該市土左旗2015年引進的億元以上重點工業專案,致力於發展新能源電池、電機、電控等核心零部件生產以及整車製造等延伸產業鏈。

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

    【其他文章推薦】

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

    小三通物流營運型態?

    ※快速運回,大陸空運推薦?

  • 前端每周學習分享–第12期

    1.VuePress

    大家看過不少Vue.js及其子項目的文檔,一定發現了它們風格完全一致,界面清爽,讀起來很舒服,它們都使用了vuepress。

    VuePress是尤大為了支持 Vue 及其子項目的文檔需求而寫的一個靜態網站生成工具,廣泛用於編寫技術文檔 ,可以部署在github上做個人博客。

    原理:

    在構建過程中,會創建應用程序的服務器渲染版本,通過訪問每個路由,來渲染相應的 HTML。

    其中, 每個 markdown 文件都使用 編譯為 HTML,然後作為 Vue 組件的模板進行處理。這允許你直接在 markdown 文件中使用 Vue,在需要嵌入動態內容時,這種使用方式非常有用。

    十分實用的特性:

    • md文件可內嵌vue代碼
    • 可自定義主題
    • 利用service worker做離線緩存
    • 多語言支持
    • 基於git的最近更新

    官方文檔:

    快速搭建:

    2.WebWorker

    web worker是運行在後台的jacvascript,利用類似線程的消息傳遞實現并行,獨立於其他腳本,不會影響頁面的性能。

    web worker能夠長時間運行,有理想的啟動性能以及理想的內存消耗。

    worker 創建后,它可以向它的創建者指定的事件監聽函數傳遞消息,這樣該worker生成的所有任務都會接收到這些消息。

    webworker有專用線程dedicated worker(單窗口專用),sharedWorker(可多窗口共享),以及後來的service worker(目前瀏覽器支持程度還不高)。

    2.1.dedicated worker

    使用方法:

    worker線程里監聽onmessage,

    頁面線程里創建worker對象:const myworker = new Worker("worker.js")

    發送消息:postMessage(msg)

    接受消息:onmessage = function(e){const msg = e.data}

    msg的數據格式自行定義。

    終止worker:myworker.terminate()

    例如下面的示例,worker會接收頁面上輸入的兩個数字,計算出乘積后返回結果。

    worker.js

    onmessage = function(e) {
      console.log('Worker: Message received from main script');
      let result = e.data[0] * e.data[1];
      if (isNaN(result)) {
        postMessage('Please write two numbers');
      } else {
        let workerResult = 'Result: ' + result;
        console.log('Worker: Posting message back to main script');
        postMessage(workerResult);
      }
    }

    index.html里

    const first = document.querySelector('#number1');
    const second = document.querySelector('#number2');
    const result = document.querySelector('.result');
    if (window.Worker) {
        const myWorker = new Worker("worker.js");
    
        first.onchange = function() {
          myWorker.postMessage([first.value, second.value]);
          console.log('Message posted to worker');
        }
    
        second.onchange = function() {
          myWorker.postMessage([first.value, second.value]);
          console.log('Message posted to worker');
        }
    
        myWorker.onmessage = function(e) {
            result.textContent = e.data;
            console.log('Message received from worker');
        }
    } else {
        console.log('Your browser doesn\'t support web workers.')
    }

    2.2.shared worker

    共享進程可以連接到多個不同的頁面,這些頁面必須屬於相同的域(相同的協議,主機以及端口)

    在火狐中,共享進程不能在私有與公共文檔間進行共享。

    SharedWorker.port返回一個MessagePort對象,用來進行通信和對共享進程進行控制。

    創建共享進程對象:const myWorker = new SharedWorker("worker.js");

    獲取端口:

    發送消息:myWorker.port.postMessage(msg)

    接收消息:myWorker.port.onmessage = function(e) {const msg = e.data}

    worker線程獲取端口:onconnect = function(e) {const port = e.ports[0]}

    啟動端口:port.start()

    2.3.service worker

    Service Worker 可以理解為一個介於客戶端和服務器之間的一個代理服務器 ,常用於做離線資源緩存

    出於對安全問題的考慮,Service Worker 只能被使用在 https 或者本地的 localhost 環境下。

    暫時沒有仔細學這塊,可以閱讀。

    參考文章:

    3.代碼相關

    3.1.元素內文本垂直居中

    已知元素高度的話,可以設置line-height:元素高度.

    如果元素高度未知,就不能使用line-height了。

    有人會想使用line-height:100%,會發現這是不行的,這個百分比是相對當前字體尺寸,而不是元素高度。

    我使用了flex布局實現

        display: flex;
        align-items:center;
        justify-content:center;

    還可以設置padding來使文本看起來垂直居中

    padding: 50px 20px;

    3.2.微信小程序自定義placeholder的隱藏時機

    在一個searchBar組件中,有一個自定的placeholder如下:

    <!-- <view
    ​        wx:if="{{!inputValue.length}}"
    ​        class="placeholder" >
    ​        {{placeholder}}
    ​     </view> -->

    原生的placeholder不是在觸發bindinput時隱藏,而是在輸入鍵盤按鈕點擊時。使用inputValue.length來判斷显示自定義的placeholder會在某些輸入法中導致拼音預覽和自定義placeholder重疊(因為拼音显示的時候value值還沒變)

    最後選擇棄用這個自定義placeholder,使用input組件的placeholder屬性,並使用placeholder-class來設置它的樣式。

    3.3.關於微信小程序原生組件的坑

    原生組件有camera、canvas、input (僅在focus時表現為原生組件) 、live-player、live-pusher、map、textarea、video、cover-view、cover-image。

    所以當你用canvas畫圖表、使用地圖、播放視頻甚至做文本輸入時,都是可能遇到相關坑點的。

    1. 關於原生組件、組件之間的層級關係、

    ​ 原生組件的層級始終高於普通組件,不論普通組件的z-index設置了多少。

    ​ 后插入的原生組件可以覆蓋之前的原生組件。

    ​ 原生組件之間的相對層級關係可以通過z-index來調整。

    ​ 原生組件會遮擋vconsole彈出的調試面板。

    ​ cover-view和cover-image可以覆蓋在部分原生組件上。

    1. cover-view的使用

    ​ cover-view在做地圖、畫布、視頻上的彈出層時是會用到的,但它有很多使用限制。

    ​ cover-view只能內嵌cover-view、cover-image、button,其他元素在真機上就會被cover-view給覆蓋住,如果想內嵌radio、picker等就只能自己用這3個可內嵌的元素來實現。

    ​ cover-view不支持iconfont,也不支持單邊border、background-imageshadowoverflow: visible等。

    1. input的使用

    ​ input在不聚焦時是佔位元素,會被原生組件遮擋,聚焦時才使用原生組件渲染。這就會出現input設置了更高的z-index,不聚焦時仍會被其他原生組件遮住。

    ​ 要解決這個問題,可以使用textarea來代替input。

    ​ 我的一個解決方案是,加一個標誌位來記錄input是否聚焦,當不聚焦時,显示一個承載value值的cover-view(它需要綁定一個觸發聚焦的點擊事件),聚焦時,就显示input組件。

    3.4.多個標籤頁之間的通信方案

    1. 使用websocket

    2. 使用localstorage或者cookie

    3. 使用sharedworker

    我遇到的問題是需要在新窗口打開當前網站的新窗口時,能繼承上一個窗口的vuex的狀態樹里的某些數據。這不需要和服務器打交道,最好就在本地。

    最後使用localstorage來做,在跳轉新窗口前更新localstorage,在新窗口根組件掛載時取出數據。

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

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務

  • 理解Spark SQL(一)—— CLI和ThriftServer

    理解Spark SQL(一)—— CLI和ThriftServer

    Spark SQL主要提供了兩個工具來訪問hive中的數據,即CLI和ThriftServer。前提是需要Spark支持Hive,即編譯Spark時需要帶上hive和hive-thriftserver選項,同時需要確保在$SPARK_HOME/conf目錄下有hive-site.xml配置文件(可以從hive中拷貝過來)。在該配置文件中主要是配置hive metastore的URI(Spark的CLI和ThriftServer都需要)以及ThriftServer相關配置項(如hive.server2.thrift.bind.host、hive.server2.thrift.port等)。注意如果該台機器上同時運行有Hive ThriftServer和Spark ThriftServer,則hive中的hive.server2.thrift.port配置的端口與spark中的hive.server2.thrift.port配置的端口要不一樣,避免同時啟動時發生端口衝突。

    啟動CLI和ThriftServer之前都需要先啟動hive metastore。執行如下命令啟動:

    [root@BruceCentOS ~]# nohup hive –service metastore &

    成功啟動后,會出現一個RunJar的進程,同時會監聽端口9083(hive metastore的默認端口)。

     

     

     先來看CLI,通過spark-sql腳本來使用CLI。執行如下命令:

    [root@BruceCentOS4 spark]# $SPARK_HOME/bin/spark-sql –master yarn

    上述命令執行後會啟動一個yarn client模式的Spark程序,如下圖所示:

      同時它會連接到hive metastore,可以在隨後出現的spark-sql>提示符下運行hive sql語句,比如:

      其中每輸入並執行一個SQL語句相當於執行了一個Spark的Job,如圖所示:

      也就是說執行spark-sql腳本會啟動一個yarn clien模式的Spark Application,而後出現spark-sql>提示符,在提示符下的每個SQL語句都會在Spark中執行一個Job,但是對應的都是同一個Application。這個Application會一直運行,可以持續輸入SQL語句執行Job,直到輸入“quit;”,然後就會退出spark-sql,即Spark Application執行完畢。

     

    另外一種更好地使用Spark SQL的方法是通過ThriftServer,首先需要啟動Spark的ThriftServer,然後通過Spark下的beeline或者自行編寫程序通過JDBC方式使用Spark SQL。

    通過如下命令啟動Spark ThriftServer:

    [root@BruceCentOS4 spark]# $SPARK_HOME/sbin/start-thriftserver.sh –master yarn

    執行上面的命令后,會生成一個SparkSubmit進程,實際上是啟動一個yarn client模式的Spark Application,如下圖所示:

      而且它提供一個JDBC/ODBC接口,用戶可以通過JDBC/ODBC接口連接ThriftServer來訪問Spark SQL的數據。具體可以通過Spark提供的beeline或者在程序中使用JDBC連接ThriftServer。例如在啟動Spark ThriftServer后,可以通過如下命令使用beeline來訪問Spark SQL的數據。

    [root@BruceCentOS3 spark]# $SPARK_HOME/bin/beeline -n root -u jdbc:hive2://BruceCentOS4.Hadoop:10003

     上述beeline連接到了BruceCentOS4上的10003端口,也就是Spark ThriftServer。所有連接到ThriftServer的客戶端beeline或者JDBC程序共享同一個Spark Application,通過beeline或者JDBC程序執行SQL相當於向這個Application提交並執行一個Job。在提示符下輸入“!exit”命令可以退出beeline。

    最後,如果要停止ThriftServer(即停止Spark Application),需要執行如下命令:

    [root@BruceCentOS4 spark]# $SPARK_HOME/sbin/stop-thriftserver.sh

     

     綜上所述,在Spark SQL的CLI和ThriftServer中,比較推薦使用後者,因為後者更加輕量,只需要啟動一個ThriftServer(對應一個Spark Application)就可以給多個beeline客戶端或者JDBC程序客戶端使用SQL,而前者啟動一個CLI就啟動了一個Spark Application,它只能給一個用戶使用。

     

     

     

     

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

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

    小三通物流營運型態?

    ※快速運回,大陸空運推薦?

  • 菲亞特董事長公開闢謠 廣汽入主消息不實

    據《歐洲汽車新聞》報導,菲亞特克萊斯勒公司(FCA)董事長約翰•埃爾坎(John Elkann)明確指出,未與中國廣汽集團簽訂股權出售協定。

    2015年FCA與廣汽延續廣汽菲亞特的合作關係,成立了廣汽菲克合資公司,投產Jeep自由光和自由俠。近日,《義大利日報》發佈了一篇爆料新聞,除在生產方面的合作外,廣汽集團還有意入主FCA,展開資本層面的聯姻。

    埃爾坎同時也是菲亞特控股集團EXOR的董事長,25日召開了Exor股東大會。針對《義大利日報》的爆料,埃爾坎當日公開闢謠,公司與廣汽集團未簽訂股權出售協定。

    埃爾坎也被詢問標緻雪鐵龍集團(PSA集團)是否可成為FCA的良好合作夥伴,該董事長則指出其公司正在尋求的推動轉型的合作夥伴,PSA並不在公司的考慮範圍內。

    據法國《回聲報》的報導,法國政府正在考慮出售其持有的PSA 14%的部分或全部股權。

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

    【其他文章推薦】

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

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    台灣海運大陸貨務運送流程

    兩岸物流進出口一站式服務