【4858.com】Net的DNS解析模块,DNS解析服务扩张缓存机制

By admin in 4858.com on 2019年4月3日

     
方今在做爬虫的学业,昨天求学的情节是有关DNS解析模块的炮制的。使用的库为ARSoft.Tools.Net,它是一个可怜强大的开源DNS控件库,包括.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻松完毕DNS客户请求端及服务器解析端。

类型地址:,

Nuget包地址:。

第2引入Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

下边开首实际完成:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

【4858.com】Net的DNS解析模块,DNS解析服务扩张缓存机制。     
近期在做爬虫的功课,明日读书的剧情是有关DNS解析模块的制作的。使用的库为ABMWX伍Soft.Tools.Net,它是3个特别有力的开源DNS控件库,包蕴.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻松完毕DNS客户请求端及服务器解析端。

品类地址:,

Nuget包地址:。

先是引入Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

上面初叶具体落到实处:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

     
在此之前我们曾经依照ARSoft.Tools.Net简言之达成了DNS解析模块的成效,不过当质量需要升高时,每叁遍爬取都要进行DNS请求,甚至很有希望1段时间内每回请求的都以一律的地点,频仍的DNS请求就会化为品质瓶颈,所以大家要透过缓存机制将DNS解析结果缓存下来,下降DNS解析操作,提高系统本性。

诸如此类,大家依据此前封装的MemoryCacheHelper类对4858.com ,DnsResolver类进行改造:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;
using Mem = Crawler.Common.MemoryCacheHelper;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public ARecord Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public TimeSpan TimeToLive { get; set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 10000)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
IsSuccess = false;
if (Mem.Contains(url))
Fill(Mem.Get(url));
else
Dig();
}

private void Fill(DnsResolver resolver)
{
TimeSpan = resolver.TimeSpan;
Url = resolver.Url;
Record = resolver.Record;
DnsServer = resolver.DnsServer;
TimeOut = resolver.TimeOut;
ReturnCode = resolver.ReturnCode;
IsSuccess = resolver.IsSuccess;
}

public void Dig()
{
//早先化DnsClient,第一个参数为DNS服务器的IP,第一个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为需求分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若再次回到结果为空,只怕存在张冠李戴,则该请求战败。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重返结果,将重回的IPV4笔录添加到结果集List中。
if (dnsMessage != null)
{
if (dnsMessage.AnswerRecords.Count > 0)
{
Record = dnsMessage.AnswerRecords[0] as ARecord;
if (Record != null)
{
IsSuccess = true;
TimeToLive=new TimeSpan(0,0,Record.TimeToLive);
Mem.Add(Url, this, TimeToLive);
}
}
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

如此,每一趟做完DNS解析后,会依据域名的TTL将分析结果缓存下来,下次查询时得以一贯调用缓存,升高系统质量。

0.什么是Redis

Redis是三个开源的利用ANSI
C言语编写、支持网络、可依据内部存款和储蓄器亦可持久化的日志型、Key-Value数据库,并提供三种语言的API

—维基百科

1.与其余用户状态保存方案相比较

style=”color: #000000;”>壹般开发中用户意况使用session可能cookie,二种艺术种种利弊。

style=”color: #000000;”>Session:在InProc形式下不难遗失,并且引起并发难点。借使应用SQLServer或许SQLServer方式又成本了品质

style=”color: #000000;”>Cookie则不难将一些用户音讯揭破,加解密同样也消耗了质量。

Redis选拔那样的方案化解了多少个难题,

一.Redis存取进程快。

二.用户数量不不难丢失。

叁.用户多的图景下不难辅助集群。

四.可见查阅在线用户。

5.力所能及完结用户1处登录。(通过代码完成,后续介绍)

陆.支撑持久化。(当然或然没什么用)

二.落到实处思路

style=”color: #000000;”>一.大家领略session其实是在cookie中保留了二个sessionid,用户每回访问都将sessionid发给服务器,服务器通过ID查找用户对应的意况数据。

style=”color: #000000;”>在此间自个儿的处理方式也是在cookie中定义1个sessionid,程序要求赢得用户情况时将sessionid做为key在Redis中搜索。

style=”color: #000000;”>二.同时session匡助用户在自然时间不访问将session回收。

style=”color: #000000;”>借用Redis中Keys援助过期岁月的风味辅助这么些效果,可是在续期方面需求程序电动拦截请求调用那几个措施(demo有例子)

下边开首代码表明

三.Redis调用接口

第3引述ServiceStack相关DLL。

style=”color: #000000;”>在web.config添加安插,那一个布局用来安装Redis调用地址每台服务用【,】隔断。主机写在第一人

 

    1 <appSettings>
    2 
    3     <!--每台Redis之间用,分割.第一个必须为主机-->
    4     <add key="SessionRedis" value="127.0.0.1:6384,127.0.0.1:6384"/>
    5 
    6 </appSettings>

初始化配置

static Managers()
{
string sessionRedis= ConfigurationManager.AppSettings[“SessionRedis”];
string timeOut = ConfigurationManager.AppSettings[“SessionRedisTimeOut”];

if (string.IsNullOrEmpty(sessionRedis))
{
throw new Exception(“web.config 贫乏配置SessionRedis,每台Redis之间用,分割.第三个必须为主机”);
}

if (string.IsNullOrEmpty(timeOut)==false)
{
TimeOut = Convert.ToInt32(timeOut);
}

var host = sessionRedis.Split(char.Parse(“,”));
var writeHost = new string[] { host[0] };
var readHosts = host.Skip(1).ToArray();

ClientManagers = new PooledRedisClientManager(writeHost, readHosts, new RedisClientManagerConfig
{
马克斯WritePoolSize = writeReadCount,//“写”链接池链接数
马克斯ReadPoolSize = writeReadCount,//“读”链接池链接数
AutoStart = true
});
}

为了操纵有益写了叁个委托

///

/// 写入
///

///
/// ///
public F TryRedisWrite(Func doWrite)
{
PooledRedisClientManager prcm = new Managers().GetClientManagers();
IRedisClient client = null;
try
{
using (client = prcm.GetClient())
{
return doWrite(client);
}
}
catch (RedisException)
{
throw new Exception(“Redis写入很是.Host:” + client.Host + “,Port:” + client.Port);
}
finally
{
if (client != null)
{
client.Dispose();
}
}
}

1个调用的例证别的的切实可行看源码

///

/// 以Key/Value的形式存储对象到缓存中
///

/// 对象类别
/// 要写入的集合 public void KSet(Dictionary value)
{
Func fun = (IRedisClient client) =>
{
client.SetAll(value);
return true;
};

TryRedisWrite(fun);
}

4.实现Session

按上面说的给cookie写一个sessionid

///

/// 用户状态管理
///

public class Session
{
///

/// 初始化
///

/// public Session(HttpContextBase _context)
{
var context = _context;
var cookie = context.Request.Cookies.Get(SessionName);
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
{
SessionId = NewGuid();
context.Response.Cookies.Add(new HttpCookie(SessionName, SessionId));
context.Request.Cookies.Add(new HttpCookie(SessionName, SessionId));
}
else
{
SessionId = cookie.Value;
}
}

}

去存取用户的办法

///

/// 获取当前用户信息
///

///
///
public object Get() where T:class,new()
{
return new RedisClient().KGet(SessionId);
}

///

/// 用户是否在线
///

///
public bool IsLogin()
{
return new RedisClient().KIsExist(SessionId);
}

///

/// 登录
///

///
/// public void Login(T obj) where T : class,new()
{
new RedisClient().KSet(SessionId, obj, new TimeSpan(0, Managers.TimeOut, 0));
}

6.续期

暗中同意用户没访问抢先二十八分钟注销用户的登录情形,所以用户每一次访问都要将用户的撤废时间推移二十六分钟

那须要调用Redis的续期方法

///

/// 延期
///

/// /// public void KSetEntryIn(string key, TimeSpan expiresTime)
{
Func fun = (IRedisClient client) =>
{
client.ExpireEntryIn(key, expiresTime);
return false;
};

TryRedisWrite(fun);
}

封装现在

///

/// 续期
///

public void Postpone()
{
new RedisClient().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0));
}

那里小编动用了MVC叁中的ActionFilter,拦截用户的具备请求

namespace Test
{
public class SessionFilterAttribute : ActionFilterAttribute
{
///

/// 每次请求都续期
///

/// public override void OnActionExecuting(ActionExecutingContext filterContext)
{
new Session(filterContext.HttpContext).Postpone();
}
}
}

在Global.asax中要登记一下

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new SessionFilterAttribute());
}

protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}

五.调用艺术

为了方便调用借用4.0中的新特点,把Controller添加一个恢宏属性

public static class ExtSessions
{public static Session SessionExt(this Controller controller)
{
return new Session(controller.HttpContext);
}
}

调用方法

public class HomeController : Controller
{
public ActionResult Index()
{
this.SessionExt().IsLogin();
return View();
}
}

陆.代码下载

点击下载

7.后续

SessionManager包涵 获取用户列表数量,注销有个别用户,依据用户ID获取用户新闻,在线用户对象列表,在线用户SessionId列表等形式

 

 

 

 

 

懂的采取方法后大家得以对它做越来越封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//伊始化DnsClient,第3个参数为DNS服务器的IP,第3个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
提姆eSpan = s.Elapsed;
//若重返结果为空,或然存在指鹿为马,则该请求退步。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重返结果,将回到的IPV4记下添加到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块就核心告竣了,至于缘何标题中标注了半成品,是因为自个儿想在中央的DNS解析功用的基础上依据分析到DNS音讯中的TTL做1套新闻缓存机制,收缩不须求的重新查询,近日还在思量使用何种情势,后续落成会更新。

懂的使用方法后大家能够对它做越来越封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//开始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若再次来到结果为空,或然存在指鹿为马,则该请求失利。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重临结果,将重回的IPV4笔录添加到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块就主题截至了,至于怎么标题中标注了半成品,是因为本身想在着力的DNS解析效用的功底上依照分析到DNS音信中的TTL做一套信息缓存机制,减弱不需求的再一次查询,最近还在设想使用何种措施,后续完结会更新。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Copyright @ 2010-2019 美高梅手机版4858 版权所有