Rumah > Operasi dan penyelenggaraan > Nginx > Cara menggunakan nginx lua untuk mengumpul data dalam statistik tapak web

Cara menggunakan nginx lua untuk mengumpul data dalam statistik tapak web

WBOY
Lepaskan: 2023-05-28 17:32:48
ke hadapan
1001 orang telah melayarinya

Juruweb dan pengendali sering menggunakan alat analisis data tapak web, Statistik Baidu, Analitis Tencent, dll. Jika anda ingin mengumpul data statistik, anda mesti terlebih dahulu mengumpul data pengumpulan data, dan membina sistem pengumpulan data.

Analisis prinsip pengumpulan data

Ringkasnya, alat analisis statistik tapak web perlu mengumpul gelagat pengguna yang melayari tapak web sasaran (seperti membuka web tertentu halaman, mengklik butang tertentu, menambahkan item pada troli beli-belah, dsb.) dan data tingkah laku tambahan (seperti jumlah pesanan yang dijana oleh gelagat pesanan, dsb.). Perangkaan awal tapak web selalunya mengumpul hanya satu gelagat pengguna: pembukaan halaman. Kemudian tingkah laku pengguna pada halaman tidak dapat dikumpulkan. Strategi pengumpulan ini boleh memenuhi perspektif analisis biasa seperti analisis trafik asas, analisis sumber, analisis kandungan dan atribut pelawat Walau bagaimanapun, dengan penggunaan meluas teknologi ajax dan tapak web e-dagang, permintaan untuk analisis statistik sasaran e-dagang semakin meningkat. lebih kuat dan lebih kukuh, strategi pengumpulan tradisional ini telah melampaui kemampuannya.
Kemudian, Google secara inovatif memperkenalkan skrip pengumpulan data yang boleh disesuaikan dalam produk Google Analitisnya Melalui antara muka yang boleh diperluas yang ditakrifkan oleh Google Analitis, pengguna hanya perlu menulis sejumlah kecil kod javascript untuk melaksanakan acara tersuai dan penjejakan dan analisis metrik. Pada masa ini, produk seperti Baidu Statistics dan Sogou Analytics telah menyalin model Google Analytics.
Malah, prinsip asas dan proses kedua-dua mod pengumpulan data adalah sama, tetapi yang terakhir mengumpul lebih banyak maklumat melalui JavaScript. Mari kita lihat prinsip asas pengumpulan data untuk pelbagai alat statistik tapak web hari ini.

Gambaran Keseluruhan Proses

Pertama sekali, tingkah laku pengguna akan mencetuskan permintaan http daripada penyemak imbas ke halaman yang sedang dikira laman web. Apabila halaman web dibuka, coretan javascript yang dibenamkan dalam halaman akan dilaksanakan Rakan-rakan yang telah menggunakan alatan yang berkaitan harus tahu bahawa alat statistik tapak web umum akan memerlukan pengguna untuk menambahkan sekeping kecil kod javascript pada halaman web biasanya akan mencipta skrip secara dinamik, dan mengarahkan src ke fail js yang berasingan Pada masa ini, fail js yang berasingan ini (nod hijau dalam Rajah 1) akan diminta dan dilaksanakan oleh pelayar ini skrip. Selepas pengumpulan data selesai, js akan meminta skrip pengumpulan data bahagian belakang (belakang dalam Rajah 1 Skrip ini biasanya merupakan program skrip dinamik yang menyamar sebagai imej, yang mungkin ditulis oleh php, python atau bahagian pelayan lain). bahasa ditanam dalam respons http kepada pelanggan.
Di atas adalah proses umum pengumpulan data Yang berikut menggunakan Google Analitis sebagai contoh untuk menjalankan analisis yang agak terperinci bagi setiap peringkat.

Fasa pelaksanaan skrip terkubur

Untuk menggunakan Google Analitis (selepas ini dirujuk sebagai GA), anda perlu memasukkan serpihan javascript yang disediakan olehnya ke dalam halaman ini sering digunakan Ia dipanggil kod terkubur.

di mana _gaq ialah tatasusunan global GA, digunakan untuk meletakkan pelbagai konfigurasi Format bagi setiap konfigurasi ialah:

_gaq.push([‘Action’, ‘param1&rsquo ;, &lsquo. ;param2’, …]);

Tindakan menentukan tindakan konfigurasi, diikuti dengan senarai parameter yang berkaitan. Kod benam lalai yang diberikan oleh GA akan memberikan dua konfigurasi pratetap _setAccount digunakan untuk menetapkan ID pengenalan tapak web ini diberikan semasa mendaftarkan GA. _trackPageview memberitahu GA untuk menjejaki lawatan halaman. Untuk konfigurasi lanjut, sila rujuk: https://developers.google.com/analytics/devguides/collection/gajs/. Sebenarnya, _gaq ini digunakan sebagai baris gilir FIFO, dan kod konfigurasi tidak perlu muncul sebelum kod yang terkubur untuk butiran, sila rujuk arahan dalam pautan di atas.
Setakat artikel ini, mekanisme _gaq bukan fokus pada kod fungsi tanpa nama di belakangnya. Tujuan utama kod ini adalah untuk memperkenalkan fail js luaran (ga.js) dengan mencipta skrip melalui kaedah document.createElement dan menghalakan src ke ga.js yang sepadan mengikut protokol (http atau https), dan akhirnya menambah elemen ini Masukkan ke dalam pepohon DOM halaman.
Perhatikan bahawa ga.async = true bermaksud memanggil fail js luaran secara tidak segerak, iaitu, tidak menyekat penghuraian penyemak imbas dan melaksanakannya secara tidak segerak selepas muat turun js luaran selesai. Atribut ini baru diperkenalkan dalam HTML5.

Fasa pelaksanaan skrip pengumpulan data

Skrip pengumpulan data (ga.js) akan dilaksanakan selepas diminta Skrip ini biasanya melakukan perkara berikut:
1. Mengumpul maklumat melalui objek javascript terbina dalam penyemak imbas, seperti tajuk halaman (melalui dokumen .title ), perujuk (URL sebelumnya, melalui document.referrer), resolusi monitor pengguna (melalui windows.screen), maklumat kuki (melalui document.cookie) dan maklumat lain.
2. Parse _gaq untuk mengumpul maklumat konfigurasi. Ini mungkin termasuk penjejakan acara yang ditentukan pengguna, data perniagaan (seperti nombor produk di tapak web e-dagang, dsb.).
3. Parsing dan sambung data yang dikumpul dalam dua langkah di atas mengikut format yang telah ditetapkan.
4. Minta skrip back-end dan letakkan maklumat dalam parameter permintaan http dan bawa ke skrip back-end.
Satu-satunya masalah di sini ialah langkah 4. Kaedah biasa untuk JavaScript meminta skrip bahagian belakang ialah ajax, tetapi ajax tidak boleh membuat permintaan merentas domain. Di sini ga.js dilaksanakan dalam domain tapak web yang sedang dikira dan skrip bahagian belakang berada dalam domain lain (skrip statistik hujung belakang GA ialah http://www.google-analytics.com/__utm.gif), dan ajax tidak berfungsi. Kaedah biasa ialah mencipta objek Imej dalam skrip js, arahkan atribut src objek Imej ke skrip hujung belakang dan bawa parameter Pada masa ini, permintaan merentas domain ke hujung belakang dilaksanakan. Inilah sebabnya mengapa skrip bahagian belakang sering menyamar sebagai fail gif. Melalui tangkapan paket http, anda boleh melihat permintaan ga.js kepada __utm.gif.

Anda dapat melihat bahawa ga.js membawa banyak maklumat apabila meminta __utm.gif Contohnya, utmsr=1280×1024 ialah resolusi skrin, utmac=UA-35712773-1 ialah nilai yang dihuraikan daripada _gaq. ID pengenalan GA dan sebagainya.
Perlu diambil perhatian bahawa __utm.gif bukan sahaja boleh diminta apabila kod terbenam dilaksanakan Jika penjejakan acara dikonfigurasikan dengan _trackEvent, skrip ini juga akan diminta apabila acara itu berlaku.
Memandangkan ga.js telah dimampatkan dan dikelirukan, dan kebolehbacaannya sangat lemah, kami tidak akan menganalisisnya, saya akan melaksanakan skrip dengan fungsi yang serupa dalam peringkat pelaksanaan kemudian.

Fasa pelaksanaan skrip bahagian belakang

__utm.gif GA ialah skrip yang menyamar sebagai gif. Skrip belakang jenis ini secara amnya perlu melengkapkan perkara berikut:
1. Menghuraikan maklumat parameter permintaan http.
2. Dapatkan beberapa maklumat daripada pelayan (WebServer) yang tidak dapat diperolehi oleh pelanggan, seperti IP pelawat, dsb.
3. Tulis maklumat ke dalam log mengikut format.
4. Hasilkan imej gif kosong 1&kali;1 sebagai kandungan respons dan tetapkan jenis Kandungan pengepala respons kepada imej/gif.
5. Tetapkan beberapa maklumat kuki yang diperlukan dalam pengepala respons melalui Set-cookie.
Sebab mengapa kuki ditetapkan adalah kerana jika anda ingin menjejaki pelawat unik, pendekatan biasa ialah jika pelanggan didapati tidak mempunyai kuki penjejakan tertentu semasa membuat permintaan, kuki unik secara global dijana mengikut kepada peraturan dan ditanam kepada pengguna, jika tidak Set-cookie Letakkan kuki penjejakan yang diperoleh ke dalam untuk memastikan kuki pengguna yang sama tidak berubah (lihat Rajah 4).

Walaupun pendekatan ini tidak sempurna (contohnya, pengguna yang mengosongkan kuki atau menukar penyemak imbas akan dianggap sebagai dua pengguna), ia kini merupakan kaedah yang digunakan secara meluas. Ambil perhatian bahawa jika tidak ada keperluan untuk menjejaki pengguna yang sama di seluruh tapak, anda boleh menggunakan js untuk menanam kuki di bawah domain tapak web yang dikira (GA melakukan ini jika anda ingin meletakkan keseluruhan rangkaian secara seragam, anda boleh menanam kuki dalam domain pelayan melalui skrip bahagian belakang Seterusnya (pelaksanaan kami akan melakukannya kemudian).

Reka bentuk dan pelaksanaan sistem

Berdasarkan prinsip di atas, saya membina sendiri sistem pengumpulan log akses.
Saya panggil sistem ini MyAnalytics.

Tentukan maklumat yang dikumpul

Demi kesederhanaan, saya tidak akan melaksanakan model pengumpulan data penuh GA, sebaliknya mengumpulkan maklumat tersebut.

Kod terkubur

Saya akan belajar daripada model GA untuk kod terkubur, tetapi pada masa ini objek konfigurasi tidak akan digunakan sebagai baris gilir FIFO.

Saya sedang menggunakan skrip statistik yang dipanggil ma.js dan telah mendayakan nama domain sekunder analytics.codinglabs.org. Sudah tentu, terdapat masalah kecil di sini, kerana saya tidak mempunyai pelayan https, jadi jika kod itu digunakan di tapak https, akan ada masalah, tetapi mari kita abaikan di sini.

Skrip statistik bahagian hadapan

Saya menulis skrip statistik ma.js yang tidak begitu lengkap tetapi boleh menyiapkan kerja asas:

    (function () {
    var params = {};
    //Document对象数据
    if(document) {
    params.domain = document.domain || '';
    params.url = document.URL || '';
    params.title = document.title || '';
    params.referrer = document.referrer || '';
    }
    //Window对象数据
    if(window && window.screen) {
    params.sh = window.screen.height || 0;
    params.sw = window.screen.width || 0;
    params.cd = window.screen.colorDepth || 0;
    }
    //navigator对象数据
    if(navigator) {
    params.lang = navigator.language || '';
    }
    //解析_maq配置
    if(_maq) {
    for(var i in _maq) {
    switch(_maq[i][0]) {
    case '_setAccount':
    params.account = _maq[i][1];
    break;
    default:
    break;
    }
    }
    }
    //拼接参数串
    var args = '';
    for(var i in params) {
    if(args != '') {
    args += '&';
    }
    args += i + '=' + encodeURIComponent(params[i]);
    }
    //通过Image对象请求后端脚本
    var img = new Image(1, 1);
    img.src = 'http://analytics.codinglabs.org/1.gif?' + args;
    })();
Salin selepas log masuk

Letakkan keseluruhan skrip Dalam fungsi tanpa nama, pastikan persekitaran global tidak tercemar. Fungsi telah dijelaskan dalam bahagian prinsip dan tidak akan diterangkan lagi. Antaranya 1.gif ialah skrip back-end.

Format log

Log menggunakan satu rekod setiap baris, menggunakan aksara tidak kelihatan ^A (kod ascii 0x01, di bawah Linux, anda boleh menggunakan ctrl + v ctrl + a Input, "^A" digunakan di bawah untuk mewakili aksara halimunan 0x01), format khusus adalah seperti berikut:
Masa^AIP^ADnama domain^AURL^APage title^AReferrer^AHresolusi tinggi^AResolution wide^AColor Depth^ALanguage ^AClient information^AUser ID^AWebsite ID

Skrip belakang

为了简单和效率考虑,我打算直接使用nginx的access_log做日志收集,不过有个问题就是nginx配置本身的逻辑表达能力有限,所以我选用了OpenResty做这个事情。OpenResty是一个基于Nginx扩展出的高性能应用开发平台,内部集成了诸多有用的模块,其中的核心是通过ngx_lua模块集成了Lua,从而在nginx配置文件中可以通过Lua来表述业务。关于这个平台我这里不做过多介绍,感兴趣的同学可以参考其官方网站http://openresty.org/,或者这里有其作者章亦春(agentzh)做的一个非常有爱的介绍OpenResty的slide:http://agentzh.org/misc/slides/ngx-openresty-ecosystem/,关于ngx_lua可以参考:https://github.com/chaoslawful/lua-nginx-module。
首先,需要在nginx的配置文件中定义日志格式:
log_format tick “$msec^A$remote_addr^A$u_domain^A$u_url^A$u_title^A$u_referrer^A$u_sh^A$u_sw^A$u_cd^A$u_lang^A$http_user_agent^A$u_utrace^A$u_account”;
注意这里以u_开头的是我们待会会自己定义的变量,其它的是nginx内置变量。
然后是核心的两个location:

    location /1.gif {
    #伪装成gif文件
    default_type image/gif;
    #本身关闭access_log,通过subrequest记录log
    access_log off;
    access_by_lua "
    -- 用户跟踪cookie名为__utrace
    local uid = ngx.var.cookie___utrace
    if not uid then
    -- 如果没有则生成一个跟踪cookie,算法为md5(时间戳+IP+客户端信息)
    uid = ngx.md5(ngx.now() .. ngx.var.remote_addr .. ngx.var.http_user_agent)
    end
    ngx.header['Set-Cookie'] = {'__utrace=' .. uid .. '; path=/'}
    if ngx.var.arg_domain then
    -- 通过subrequest到/i-log记录日志,将参数和用户跟踪cookie带过去
    ngx.location.capture('/i-log?' .. ngx.var.args .. '&utrace=' .. uid)
    end
    ";
    #此请求不缓存
    add_header Expires "Fri, 01 Jan 1980 00:00:00 GMT";
    add_header Pragma "no-cache";
    add_header Cache-Control "no-cache, max-age=0, must-revalidate";
    #返回一个1×1的空gif图片
    empty_gif;
    }
    location /i-log {
    #内部location,不允许外部直接访问
    internal;
    #设置变量,注意需要unescape
    set_unescape_uri $u_domain $arg_domain;
    set_unescape_uri $u_url $arg_url;
    set_unescape_uri $u_title $arg_title;
    set_unescape_uri $u_referrer $arg_referrer;
    set_unescape_uri $u_sh $arg_sh;
    set_unescape_uri $u_sw $arg_sw;
    set_unescape_uri $u_cd $arg_cd;
    set_unescape_uri $u_lang $arg_lang;
    set_unescape_uri $u_utrace $arg_utrace;
    set_unescape_uri $u_account $arg_account;
    #打开日志
    log_subrequest on;
    #记录日志到ma.log,实际应用中最好加buffer,格式为tick
    access_log /path/to/logs/directory/ma.log tick;
    #输出空字符串
    echo '';
    }
Salin selepas log masuk

要完全解释这段脚本的每一个细节有点超出本文的范围,而且用到了诸多第三方ngxin模块(全都包含在OpenResty中了),重点的地方我都用注释标出来了,可以不用完全理解每一行的意义,只要大约知道这个配置完成了我们在原理一节提到的后端逻辑就可以了。

日志轮转

日志收集系统需要处理大量的访问日志,在时间的累积下文件规模急剧膨胀,放在同一文件中管理不便。所以通常要按时间段将日志切分,例如每天或每小时切分一个日志。我这里为了效果明显,每一小时切分一个日志。通过 crontab 定时调用一个 shell 脚本,以下是该脚本的内容:

    _prefix="/path/to/nginx"
    time=`date +%Y%m%d%H`
    mv ${_prefix}/logs/ma.log ${_prefix}/logs/ma/ma-${time}.log
    kill -USR1 `cat ${_prefix}/logs/nginx.pid`
Salin selepas log masuk

这个脚本将ma.log移动到指定文件夹并重命名为ma-{yyyymmddhh}.log,然后向nginx发送USR1信号令其重新打开日志文件。
然后再/etc/crontab里加入一行:

59 * * * * root /path/to/directory/rotatelog.sh
Salin selepas log masuk

在每个小时的59分启动这个脚本进行日志轮转操作。

测试

下面可以测试这个系统是否能正常运行了。我昨天就在我的博客中埋了相关的点,通过http抓包可以看到ma.js和1.gif已经被正确请求。
同时可以看一下1.gif的请求参数。
相关信息确实也放在了请求参数中。
然后我tail打开日志文件,然后刷新一下页面,因为没有设access log buffer, 我立即得到了一条新日志:
1351060731.360^A0.0.0.0^Awww.codinglabs.org^Ahttp://www.codinglabs.org/^ACodingLabs^A^A1024^A1280^A24^Azh-CN^AMozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4^A4d612be64366768d32e623d594e82678^AU-1-1
注意实际上原日志中的^A是不可见的,这里我用可见的^A替换为方便阅读,另外IP由于涉及隐私我替换为了0.0.0.0。

关于分析

通过上面的分析和开发可以大致理解一个网站统计的日志收集系统是如何工作的。有了这些日志,就可以进行后续的分析了。本文只注重日志收集,所以不会写太多关于分析的东西。
注意,原始日志最好尽量多的保留信息而不要做过多过滤和处理。例如上面的MyAnalytics保留了毫秒级时间戳而不是格式化后的时间,时间的格式化是后面的系统做的事而不是日志收集系统的责任。后面的系统根据原始日志可以分析出很多东西,例如通过IP库可以定位访问者的地域、user agent中可以得到访问者的操作系统、浏览器等信息,再结合复杂的分析模型,就可以做流量、来源、访客、地域、路径等分析了。当然,一般不会直接对原始日志分析,而是会将其清洗格式化后转存到其它地方,如MySQL或HBase中再做分析。
分析部分的工作有很多开源的基础设施可以使用,例如实时分析可以使用Storm,而离线分析可以使用Hadoop。当然,在日志比较小的情况下,也可以通过shell命令做一些简单的分析,例如,下面三条命令可以分别得出我的博客在今天上午8点到9点的访问量(PV),访客数(UV)和独立IP数(IP):

    awk -F^A '{print $1}' ma-2012102409.log | wc -l
    awk -F^A '{print $12}' ma-2012102409.log | uniq | wc -l
    awk -F^A '{print $2}' ma-2012102409.log | uniq | wc -l
Salin selepas log masuk

Atas ialah kandungan terperinci Cara menggunakan nginx lua untuk mengumpul data dalam statistik tapak web. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan