Rumah > Artikel > pembangunan bahagian belakang > Pengesyoran konfigurasi cache DNS untuk setiap bahasa pembangunan
Pengarang: Zhai Helong
Dalam bidang komputer, salah satu prinsip pertama yang harus dipertimbangkan apabila ia berkaitan dengan prestasi tindakan pengoptimuman adalah Menggunakan cache, mekanisme caching data yang munasabah boleh membawa faedah berikut:
1 Memendekkan laluan pemerolehan data dan cache data hotspot berdekatan untuk bacaan pantas seterusnya, dengan itu bertambah baik dengan ketara. kecekapan pemprosesan;
2. Mengurangkan kekerapan pemerolehan data jauh, mengurangkan tekanan pada perkhidmatan data bahagian belakang dan mengurangkan kos jalur lebar rangkaian antara bahagian hadapan dan bahagian belakang;
Daripada reka bentuk cache pelbagai peringkat perkakasan CPU, kepada paparan pantas halaman oleh penyemak imbas, kepada produk komersial yang popular seperti CDN dan gerbang storan awan, konsep caching digunakan di mana-mana.
Dalam medan rangkaian awam, mekanisme caching produk matang seperti sistem pengendalian, penyemak imbas dan APP mudah alih telah banyak menghapuskan masalah yang dihadapi oleh penyedia rangkaian seperti China Telecom, China Mobile , China Unicom dan pembekal kandungan seperti platform portal utama dan vendor CDN menghadapi tekanan perkhidmatan Hanya DNS pengendali boleh menghadapi ratusan juta resolusi DNS sesaat, kluster peralatan rangkaian boleh menanggung Internet peringkat Tbit dengan mudah. lebar jalur sesaat, dan platform CDN boleh Mengendalikan berbilion-bilion permintaan sesaat dengan cepat.
Menghadapi skala capaian nama domain yang besar dan berkembang semasa syarikat, pasukan pengarang sentiasa mengoptimumkan seni bina kluster dan meningkatkan prestasi perisian DNS Ia juga perlu mempromosikan pelbagai aspek dengan segera akses nama domain. Optimumkan mekanisme permintaan resolusi nama domain dalam persekitaran seperti pelanggan Oleh itu, kami secara khusus mengatur ahli pasukan untuk menyelidik dan menulis artikel panduan ini untuk memberikan cadangan yang munasabah untuk kakitangan pembangunan dan operasi bahagian hadapan syarikat. , pelanggan dan rakan kongsi, dan mengoptimumkan keseluruhan proses permintaan DNS untuk meningkatkan kecekapan perniagaan.
Artikel ini membincangkan terutamanya cara melaksanakan cache rekod resolusi DNS secara setempat pada klien di bawah latar belakang bahasa perniagaan dan pembangunan yang berbeza Pada masa yang sama, berdasarkan pemahaman pasukan pengarang tentang DNS itu sendiri dan persekitaran rangkaian syarikat, Memandangkan beberapa langkah tambahan, akhirnya berusaha ke arah menormalkan permintaan resolusi DNS pada pihak pelanggan.
Klien yang disebut dalam artikel ini secara amnya merujuk kepada semua objek yang secara aktif memulakan permintaan rangkaian, termasuk. tetapi Tidak terhad kepada pelayan, PC, terminal mudah alih, sistem pengendalian, alat baris arahan, skrip, perisian perkhidmatan, Apl pengguna, dsb.
Sistem Nama Domain (Pelayan/Perkhidmatan), sistem nama domain (pelayan/perkhidmatan), boleh difahami sebagai sejenis perkhidmatan pangkalan data; 🎜>
Pelanggan bergantung pada alamat IP untuk mengenal pasti antara satu sama lain apabila berkomunikasi dengan pelayan Sebagai pengguna pelanggan, sukar bagi manusia untuk mengingati sejumlah besar alamat IP, jadi nama domain yang mudah diingat seperti www. jd.com, menyimpan hubungan pemetaan antara nama domain dan alamat IP dalam DNS untuk pertanyaan klien; pelayan dengan memulakan permintaan resolusi nama domain kepada DNS Selepas mendapatkan alamat, anda boleh memulakan permintaan komunikasi rangkaian ke alamat IP dan benar-benar mendapatkan perkhidmatan atau kandungan yang dibawa oleh nama domain.
Rujukan: Sistem Nama Domain Proses Penyelesaian Nama Domain
3. LDNSDNS Tempatan, nama domain tempatan pelayan; awam Persekitaran akses rangkaian biasanya ditetapkan secara automatik oleh pembekal rangkaian (pembekal mempunyai kawalan dan juga boleh melakukan rampasan DNS, iaitu, mengganggu IP yang diperoleh daripada resolusi nama domain), dan persekitaran intranet ditetapkan secara automatik oleh Jabatan IT;
Biasanya sistem Unix, Unix dan MacOS boleh menyemak LDNS mereka sendiri melalui /etc/resolv.conf Selepas pelayan nama, dinyatakan bahawa fail ini turut menyokong penyuntingan sendiri dan pengubahsuaian pengguna untuk menentukan LDNS, seperti yang biasa pada rangkaian awam seperti DNS Google, 114DNS, dsb. dalam persekitaran intranet tulen, ia biasanya tidak disyorkan untuk mengubah suai tanpa berunding dengan jabatan IT , yang boleh menyebabkan perkhidmatan tidak tersedia; sila rujuk
man resolv.confHasil arahan. Apabila resolusi nama domain tidak normal, kemungkinan keabnormalan perkhidmatan LDNS atau rampasan resolusi juga harus dipertimbangkan.
Rujukan: Ubah suai tetapan TCP/IP (termasuk DNS) dalam sistem windows
4 boleh Secara dinamik menyediakan hubungan pemetaan antara nama domain dan IP Fail hos, yang biasa dalam pelbagai sistem pengendalian, ialah fail rekod statik hubungan pemetaan antara nama domain dan IP Biasanya rekod hos diutamakan daripada resolusi DNS , apabila tiada cache tempatan atau cache terlepas , rekod nama domain yang sepadan akan ditanya melalui hos terlebih dahulu. Jika tiada pemetaan yang berkaitan untuk hos, permintaan DNS akan terus dimulakan. Untuk mengawal logik ini dalam persekitaran Linux, sila rujuk bahagian pengenalan cache DNS bahasa C/C++ di bawah.Jadi dalam kerja sebenar, ciri lalai di atas sering digunakan untuk menulis hubungan pemetaan antara nama domain tertentu dan IP tertentu ke dalam fail hos (biasanya dikenali sebagai "hos tetap"), yang digunakan untuk memintas proses resolusi DNS dan memetakan IP sasaran Untuk akses yang disasarkan (kesannya adalah sama dengan pilihan -x curl, atau pilihan proksi -e untuk wget Masa Untuk -Hidup, nilai masa kelangsungan hidup, konsep ini boleh digunakan dalam banyak bidang dan mungkin mempunyai maksud yang berbeza. Penerangan TTL yang terlibat dalam artikel ini semuanya untuk caching data Ia boleh difahami secara langsung sebagai "tempoh sah" data cache. Ia bermula dari masa data dicache dan wujud dalam cache lebih daripada Data dengan tempoh yang ditentukan oleh TTL dianggap sebagai data tamat tempoh Apabila data dipanggil semula, kesahihan akan disahkan atau diperoleh semula serta-merta daripada sumber data yang berwibawa. Oleh kerana mekanisme caching biasanya dicetuskan dan dikemas kini secara pasif, jika data autoritatif asal bahagian belakang berubah semasa tempoh sah cache pelanggan, pelanggan tidak akan mengesannya, yang akan menyebabkan keadaan tertentu masalah perniagaan. Terdapat tahap kelewatan kemas kini data tertentu dan ketidakkonsistenan sementara antara data cache dan data berwibawa. Untuk TTL cache rekod DNS pihak pelanggan, kami mengesyorkan nilai 60s pada masa yang sama, jika ia adalah perniagaan sensitiviti rendah seperti ujian atau perniagaan dengan pelarasan resolusi nama domain yang jarang berlaku, ia boleh dilanjutkan dengan sewajarnya , malah mencapai tahap jam atau hari Hasil tinjauan berikut disyorkan untuk dirujuk oleh pembangun bagi melaksanakan caching DNS klien yang dibangunkan sendiri. Setiap bahasa pembangunan mungkin mempunyai sokongan yang berbeza untuk cache DNS. Mari analisanya satu per satu di sini. (1) fungsi getaddrinfo glibc Pustaka glibc dalam persekitaran Linux menyediakan dua Domain fungsi resolusi nama: fungsi gethostbyname dan fungsi getaddrinfo ialah fungsi yang biasa digunakan pada masa lalu, tetapi dengan peralihan kepada IPv6 dan model pengaturcaraan berulir, getaddrinfo menjadi lebih berguna kerana ia bukan sahaja menghuraikan alamat IPv6 tetapi juga selamat untuk thread disyorkan untuk menggunakan fungsi getaddrinfo. Prototaip fungsi: Fungsi getaddrinfo ialah fungsi perpustakaan asas peringkat rendah yang banyak dalam pembangunan bahasa bergantung pada fungsi ini, jadi kami memperkenalkan logik pemprosesan fungsi ini di sini. Jejaki panggilan sistem fungsi ini melalui arahan strace. 1) Cari cache nscd (lihat di bawah untuk pengenalan kepada nscd) Kami dalam persekitaran linux Melalui arahan strace, anda boleh melihat panggilan sistem berikut Sambungkan perkhidmatan nscd untuk menanyakan cache DNS melalui antara muka soket unix "/var/run /nscd/soket". 2) Tanya fail /etc/hosts Jika perkhidmatan nscd tidak dimulakan atau cache terlepas, teruskan pertanyaan kepada hos fail dan kita sepatutnya dapat Lihat panggilan sistem berikut 3) Tanya perkhidmatan DNS Soal DNS daripada /etc/resolv.conf configuration Alamat IP pelayan (pelayan nama), dan kemudian lakukan pertanyaan DNS untuk mendapatkan keputusan resolusi. Kita boleh melihat panggilan sistem berikut dan sama ada klien perlu terlebih dahulu mencari fail /etc/hosts atau mula-mula mendapatkan pelayan DNS daripada /etc/resolv.conf untuk pertanyaan Parsing dikawal oleh /etc/nsswitch.conf: Anda sebenarnya boleh melihat melalui arahan strace bahawa selepas sistem memanggil soket nscd, sebelum membaca /etc/resolv.conf , fail akan dibaca 4) Sahkan Berdasarkan analisis di atas, adalah mungkin untuk menggabungkan fungsi getaddrinfo dengan nscd. (2) Fungsi resolusi nama domain perpustakaan libcurl pustaka libcurl ialah perpustakaan penghantaran rangkaian yang biasa digunakan oleh pelanggan dalam bahasa c/c++ , arahan curl dilaksanakan berdasarkan perpustakaan ini. Pustaka ini juga memanggil fungsi perpustakaan getaddrifo untuk melaksanakan resolusi nama domain DNS, dan juga menyokong caching DNS nscd. Bahasa Java ialah bahasa utama untuk pembangunan sistem perniagaan di banyak syarikat Sahkan sama ada perpustakaan rangkaian Java menyokongnya dengan menulis a program klien HTTP mudah untuk menguji cache DNS. Ujian ini mengesahkan dua komponen HttpURLConnection dan Apache httpcomponents-client dalam perpustakaan standard Java. (1) Pustaka standard Java HttpURLConnection 测试结果显示 Java 标准库 HttpURLConnection 是支持 DNS 缓存,5 次请求中只有一次 DNS 请求。 (2)Apache httpcomponents-client 测试结果显示 Apache httpcomponents-client 支持 DNS 缓存,5 次请求中只有一次 DNS 请求。 从测试中发现 Java 的虚拟机实现一套 DNS 缓存,即实现在 java.net.InetAddress 的一个简单的 DNS 缓存机制,默认为缓存 30 秒,可以通过 networkaddress.cache.ttl 修改默认值,缓存范围为 JVM 虚拟机进程,也就是说同一个 JVM 进程中,30秒内一个域名只会请求DNS服务器一次。同时 Java 也是支持 nscd 的 DNS 缓存,估计底层调用 getaddrinfo 函数,并且 nscd 的缓存级别比 Java 虚拟机的 DNS 缓存高。 随着云原生技术的发展,Go 语言逐渐成为云原生的第一语言,很有必要验证一下 Go 的标准库是否支持 DNS 缓存。通过我们测试验证发现 Go 的标准库 net.http 是不支持 DNS 缓存,也是不支持 nscd 缓存,应该是没有调用 glibc 的库函数,也没有实现类似 getaddrinfo 函数的功能。这个跟 Go语言的自举有关系,Go 从 1.5 开始就基本全部由 Go(.go) 和汇编 (.s) 文件写成的,以前版本的 C(.c) 文件被全部重写。不过有一些第三方 Go 版本 DNS 缓存库,可以自己在应用层实现,还可以使用 fasthttp 库的 httpclient。 (1)标准库net.http 从测试结果来看,net.http 每次都去 DNS 查询,不支持 DNS 缓存。 (2)fasthttp 库 fasthttp 库是 Go 版本高性能 HTTP 库,通过极致的性能优化,性能是标准库 net.http 的 10 倍,其中一项优化就是支持 DNS 缓存,我们可以从其源码看到 可以参考如下方法使用 fasthttp client 端 (3)第三方DNS缓存库 这个是 github 中的一个 Go 版本 DNS 缓存库 可以参考如下代码,在HTTP库中支持DNS缓存 (1)requests 库 (2)httplib2 库 (3)urllib2 库 Python 测试三种库都是支持 nscd 的 DNS 缓存的(推测底层也是调用 getaddrinfo 函数),以上测试时使用 HTTP 短连接,都在 python2 环境测试。 针对 HTTP 客户端来说,可以优先开启 HTTP 的 keep-alive 模式,可以复用 TCP 连接,这样可以减少 TCP 握手耗时和重复请求域名解析,然后再开启 nscd 缓存,除了 Go 外,C/C++、Java、Python 都可支持 DNS 缓存,减少 DNS查询耗时。 这里只分析了常用 C/C++、Java、Go、Python 语言,欢迎熟悉其他语言的小伙伴补充。 在由于某些特殊原因,自研或非自研客户端本身无法提供 DNS 缓存支持的情况下,建议管理人员在其所在系统环境中部署DNS缓存程序; 现介绍 Unix/类 Unix 系统适用的几款常见轻量级 DNS 缓存程序。而多数桌面操作系统如 Windows、MacOS 和几乎所有 Web 浏览器均自带 DNS 缓存功能,本文不再赘述。 P.S. DNS 缓存服务请务必确保随系统开机启动; name service cache daemon 即装即用,通常为 linux 系统默认安装,相关介绍可参考其 manpage:man nscd;man nscd.conf (1)安装方法:通过系统自带软件包管理程序安装,如 yum install nscd (2)缓存管理(清除): 1.service nscd restart 重启服务清除所有缓存; 2.nscd -i hosts 清除 hosts 表中的域名缓存(hosts 为域名缓存使用的 table 名称,nscd 有多个缓存 table,可参考程序相关 manpage) 较为轻量,可选择其作为 nscd 替代,通常需单独安装 (1)安装方法:通过系统自带软件包管理程序安装,如 yum install dnsmasq (2)核心文件介绍(基于 Dnsmasq version 2.86,较低版本略有差异,请参考对应版本文档如 manpage 等) (3)/etc/default/dnsmasq 提供六个变量定义以支持六种控制类功能 (4)/etc/dnsmasq.d/ 此目录含 README 文件,可参考;目录内可以存放自定义配置文件 (5)/etc/dnsmasq.conf 主配置文件,如仅配置 dnsmasq 作为缓存程序,可参考以下配置 (6)缓存管理(清除): 1.kill -s HUP `pidof dnsmasq` 推荐方式,无需重启服务 2.kill -s TERM `pidof dnsmasq` 或 service dnsmasq stop 3.service dnsmasq force-reload 或 service dnsmasq restart (7)官方文档:https://thekelleys.org.uk/dnsmasq/doc.html 以 linux 操作系统为例,常用的网络请求命令行工具常常通过调用 getaddrinfo() 完成域名解析过程,如 ping、telnet、curl、wget 等,但其可能出于通用性的考虑,均被设计为对同一个域名每次解析会发起两个请求,分别查询域名 A 记录(即 IPV4 地址)和 AAAA 记录(即 IPV6 地址)。 因目前大部分公司的内网环境及云上内网环境还未使用 ipv6 网络,故通常 DNS 系统不为内网域名添加 AAAA 记录,徒劳请求域名的 AAAA 记录会造成前端应用和后端 DNS 服务不必要的资源开销。因此,仅需请求内网域名的业务,如决定自研客户端,建议开发人员视实际情况,可将其设计为仅请求内网域名 A 记录,尤其当因故无法实施本地缓存机制时。 客户端需严格规范域名/主机名的处理逻辑,避免产生大量对不存在域名的解析请求(确保域名从权威渠道获取,避免故意或意外使用随机构造的域名、主机名),因此类请求的返回结果(NXDOMAIN)通常不被缓存或缓存时长较短,且会触发客户端重试,对后端 DNS 系统造成一定影响。5
3 cadangan pengoptimuman resolusi DNS
1 Caching DNS oleh pelbagai pustaka rangkaian bahasa
Bahasa C/C++
int getaddrinfo( const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
//连接nscd
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)
//读取 hosts 文件
open("/etc/host.conf", O_RDONLY)= 3
fstat(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0
...
open("/etc/hosts", O_RDONLY|O_CLOEXEC)= 3
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
fstat(3, {st_mode=S_IFREG|0644, st_size=178, ...}) = 0
//获取 resolv.conf 中 DNS 服务 IP
open("/etc/resolv.conf", O_RDONLY)= 3
fstat(3, {st_mode=S_IFREG|0644, st_size=25, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fef2abee000
read(3, "nameserver 114.114.114.114nn", 4096) = 25
...
//连到 DNS 服务,开始 DNS 查询
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, 16) = 0
poll([{fd=3, events=POLLOUT}], 1, 0)= 1 ([{fd=3, revents=POLLOUT}])
#/etc/nsswitch.conf 部分配置
...
#hosts: db files nisplus nis dns
hosts:files dns
...
newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=510, ...}, 0) = 0
...
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
int gethostaddr(char * name);
int main(int argc, char *argv[]){
if (argc != 2)
{
fprintf(stderr, "%s $host", argv[0]);
return -1;
}
int i = 0;
for(i = 0; i < 5; i++)
{
int ret = -1;
ret = gethostaddr(argv[1]);
if (ret < 0)
{
fprintf(stderr, "%s $host", argv[0]);
return -1;
}
//sleep(5);
}
return 0;
}
int gethostaddr(char* name){
struct addrinfo hints;
struct addrinfo *result;
struct addrinfo *curr;
int ret = -1;
char ipstr[INET_ADDRSTRLEN];
struct sockaddr_in*ipv4;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
ret = getaddrinfo(name, NULL, &hints, &result);
if (ret != 0)
{
fprintf(stderr, "getaddrinfo: %sn", gai_strerror(ret));
return ret;
}
for (curr = result; curr != NULL; curr = curr->ai_next)
{
ipv4 = (struct sockaddr_in *)curr->ai_addr;
inet_ntop(curr->ai_family, &ipv4->sin_addr, ipstr, INET_ADDRSTRLEN);
printf("ipaddr:%sn", ipstr);
}
freeaddrinfo(result);
return 0;
}
int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
Curl_addrinfo **result)
{
...
error = getaddrinfo(nodename, servname, hints, &aihead);
if(error)
return error;
...
}
Java
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpUrlConnectionDemo {
public static void main(String[] args) throws Exception {
String urlString = "http://example.my.com/";
int num = 0;
while (num < 5) {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.flush();
os.close();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
System.out.println("rsp:" + sb.toString());
} else {
System.out.println("rsp code:" + conn.getResponseCode());
}
num++;
}
}
}
import java.util.ArrayList;
import java.util.List;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
public class QuickStart {
public static void main(final String[] args) throws Exception {
int num = 0;
while (num < 5) {
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final HttpGet httpGet = new HttpGet("http://example.my.com/");
try (final CloseableHttpResponse response1 = httpclient.execute(httpGet)) {
System.out.println(response1.getCode() + " " + response1.getReasonPhrase());
final HttpEntity entity1 = response1.getEntity();
EntityUtils.consume(entity1);
}
}
num++;
}
}
}
# 默认缓存 ttl 在 jre/lib/security/java.security 修改,其中 0 是不缓存,-1 是永久缓存
networkaddress.cache.ttl=10
# 这个参数 sun.net.inetaddr.ttl 是以前默认值,目前已经被 networkaddress.cache.ttl 取代
Go
package main
import (
"flag"
"fmt"
"io/ioutil"
"net/http"
"time"
)
var httpUrl string
func main() {
flag.StringVar(&httpUrl, "url", "", "url")
flag.Parse()
getUrl := fmt.Sprintf("http://%s/", httpUrl)
fmt.Printf("url: %sn", getUrl)
for i := 0; i < 5; i++ {
_, buf, err := httpGet(getUrl)
if err != nil {
fmt.Printf("err: %vn", err)
return
}
fmt.Printf("resp: %sn", string(buf))
time.Sleep(10 * time.Second)# 等待10s发起另一个请求
}
}
func httpGet(url string) (int, []byte, error) {
client := createHTTPCli()
resp, err := client.Get(url)
if err != nil {
return -1, nil, fmt.Errorf("%s err [%v]", url, err)
}
defer resp.Body.Close()
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return resp.StatusCode, buf, err
}
return resp.StatusCode, buf, nil
}
func createHTTPCli() *http.Client {
readWriteTimeout := time.Duration(30) * time.Second
tr := &http.Transport{
DisableKeepAlives: true,//设置短连接
IdleConnTimeout: readWriteTimeout,
}
client := &http.Client{
Timeout: readWriteTimeout,
Transport: tr,
}
return client
}
//主要在fasthttp/tcpdialer.go中
type TCPDialer struct {
...
// This may be used to override DNS resolving policy, like this:
// var dialer = &fasthttp.TCPDialer{
//Resolver: &net.Resolver{
//PreferGo: true,
//StrictErrors: false,
//Dial: func (ctx context.Context, network, address string) (net.Conn, error) {
//d := net.Dialer{}
//return d.DialContext(ctx, "udp", "8.8.8.8:53")
//},
//},
// }
Resolver Resolver
// DNSCacheDuration may be used to override the default DNS cache duration (DefaultDNSCacheDuration)
DNSCacheDuration time.Duration
...
}
func main() {
// You may read the timeouts from some config
readTimeout, _ := time.ParseDuration("500ms")
writeTimeout, _ := time.ParseDuration("500ms")
maxIdleConnDuration, _ := time.ParseDuration("1h")
client = &fasthttp.Client{
ReadTimeout: readTimeout,
WriteTimeout:writeTimeout,
MaxIdleConnDuration: maxIdleConnDuration,
NoDefaultUserAgentHeader:true, // Don't send: User-Agent: fasthttp
DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
DisablePathNormalizing:true,
// increase DNS cache time to an hour instead of default minute
Dial: (&fasthttp.TCPDialer{
Concurrency:4096,
DNSCacheDuration: time.Hour,
}).Dial,
}
sendGetRequest()
sendPostRequest()
}
r := &dnscache.Resolver{}
t := &http.Transport{
DialContext: func(ctx context.Context, network string, addr string) (conn net.Conn, err error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
ips, err := r.LookupHost(ctx, host)
if err != nil {
return nil, err
}
for _, ip := range ips {
var dialer net.Dialer
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(ip, port))
if err == nil {
break
}
}
return
},
}
Python
#!/bin/python
import requests
url = 'http://example.my.com/'
num = 0
while num < 5:
headers={"Connection":"close"} # 开启短连接
r = requests.get(url,headers = headers)
print(r.text)
num +=1
#!/usr/bin/env python
import httplib2
http = httplib2.Http()
url = 'http://example.my.com/'
num = 0
while num < 5:
loginHeaders={
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.0 Chrome/30.0.1599.101 Safari/537.36',
'Connection': 'close'# 开启短连接
}
response, content = http.request(url, 'GET', headers=loginHeaders)
print(response)
print(content)
num +=1
#!/bin/python
import urllib2
import cookielib
httpHandler = urllib2.HTTPHandler(debuglevel=1)
httpsHandler = urllib2.HTTPSHandler(debuglevel=1)
opener = urllib2.build_opener(httpHandler, httpsHandler)
urllib2.install_opener(opener)
loginHeaders={
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.0 Chrome/30.0.1599.101 Safari/537.36',
'Connection': 'close' # 开启短连接
}
num = 0
while num < 5:
request=urllib2.Request('http://example.my.com/',headers=loginHeaders)
response = urllib2.urlopen(request)
page=''
page= response.read()
print response.info()
print page
num +=1
总结
2. Unix/类 Unix 系统常用 dns 缓存服务:
nscd
dnsmasq
listen-address=127.0.0.1#程序监听地址,务必指定本机内网或回环地址,避免暴露到公网环境
port=53 #监听端口
resolv-file=/etc/dnsmasq.d/resolv.conf#配置dnsmasq向自定义文件内的 nameserver 转发 dns 解析请求
cache-size=150#缓存记录条数,默认 150 条,可按需调整、适当增大
no-negcache #不缓存解析失败的记录,主要是 NXDOMAIN,即域名不存在
log-queries=extra #开启日志记录,指定“=extra”则记录更详细信息,可仅在问题排查时开启,平时关闭
log-facility=/var/log/dnsmasq.log #指定日志文件
#同时需要将本机 /etc/resolv.conf 第一个 nameserver 指定为上述监听地址,这样本机系统的 dns 查询请求才会通过 dnsmasq 代为转发并缓存响应结果。
#另 /etc/resolv.conf 务必额外配置 2 个 nameserver,以便 dnsmasq 服务异常时支持系统自动重试,注意 resolv.conf 仅读取前 3 个 nameserver
3. 纯内网业务取消查询域名的AAAA记录的请求
4. 规范域名处理逻辑
Atas ialah kandungan terperinci Pengesyoran konfigurasi cache DNS untuk setiap bahasa pembangunan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!