Nginx and InfluxDB through unix socket
InfluxDB API
向influxDB中写数据有多种方式,最熟悉的就是HTTP API了,InfluxDB 的 HTTP Service 提供了一套完整的管理接口,另外你也可以用命令行工具 influx 来操作,但是它底层也是调用的HTTP API。
另外,在一些场景中我们可能对数据的写入性能要求比较高,于是influxDB提供了 UDP 的API,UDP Service 是以服务出现的,可以在配置中开启:
[[udp]]
enabled = false
# bind-address = ""
# database = "udp"
# retention-policy = ""
# These next lines control how batching works. You should have this enabled
# otherwise you could get dropped metrics or poor performance. Batching
# will buffer points in memory if you have many coming in.
# batch-size = 1000 # will flush if this many points get buffered
# batch-pending = 5 # number of batches that may be pending in memory
# batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit
# read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max.
# set the expected UDP payload size; lower values tend to yield better performance, default is max UDP size 65536
# udp-payload-size = 65536
从配置中可以看到,需要配置一个 database
和 retention-policy
. 于是 udp 你可以配置多个,每个绑定的地址只能往对应的数据库里面写数据。GAP!
InfluxDB Unix Domain Socket
在 https://github.com/influxdata/influxdb/pull/7130 中,我向官方提交了一个unix socket service 的PR,在整个项目中,它的地位和UDP Service是一样的(逻辑地位,不是技术细节,这里也导致了influxDB官方人员的误解),作为一种服务的存在,很可惜,influxDB的官方并不想只是用unix socket来write points,由于unix socket是双向的,与TCP极为相像,于是他们想把整个HTTP Service expose出来,承载在整个unix domain socket之上。
我觉的想法非常好,于是,我又新建了一个branch work on it
配置:
[http]
enabled = true
bind-address = ":8086"
auth-enabled = false
log-enabled = true
write-tracing = false
pprof-enabled = false
https-enabled = false
https-certificate = "/etc/ssl/influxdb.pem"
### Use a separate private key location.
# https-private-key = ""
max-row-limit = 10000
realm = "InfluxDB"
unix-socket-enabled = true # enable http service over unix domain socket
bind-socket = "/var/run/influxdb.sock"
最下面我增加了两个配置:一个用于启用 unix socket, 一个用于绑定。
开启之后,HTTP API 可以同时跑在TCP和unix domain socket上
simple client 测试代码:
package main
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
)
var sock = "/tmp/test.sock"
// all your client.Get or client.Post calls has to be a valid url (http://xxxx.xxx/path not unix://...),
// the domain name doesn't matter since it won't be used in connecting.
const URL = "http://test/"
func unixsocketDial(proto, addr string) (conn net.Conn, err error) {
return net.Dial("unix", sock)
}
func main() {
tr := &http.Transport{
Dial: unixsocketDial,
}
client := &http.Client{Transport: tr}
q := url.Values{}
q.Set("db", "unixsocket")
q.Set("q", "SELECT value FROM cpu WHERE region='us_west' LIMIT 10")
req, err := http.NewRequest("GET", URL+"query?"+q.Encode(), nil)
req.Header.Add("Content-Type", "application/json;charset=UTF-8")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
更多信息参考:https://github.com/influxdata/influxdb/pull/7135
With Nginx
有意思的是nginx可以直接把http服务通过unix socket传递给后端:
upstream influxdb {
server unix:/tmp/influxdb.sock;
}
# the nginx server instance
server {
listen 80;
server_name test.com;
error_log /var/log/nginx/go_error.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1; # for keep-alive
proxy_pass http://influxdb/;
proxy_redirect off;
}
}
由于不占用本地的TCP连接,在大访问量的情况下 性能会非常好。