DNS over Httpsのクライアントを作ったらライブラリ開発者が修正してくれたお話

皆さんこんにちは! Detroit Become HumanにどっぷりハマってしまったWiNtUですw 前回の記事でDNS over Httpsを使って名前解決するクライアントをRuby + ruby-dnsで作成した記事を書きました。

ついでにGithubに公開してたのですが、なんと、ruby-dnsの開発者の一人であるSamuel Williams(@ioquatix)さんが私のプログラムを修正してくれました!!

今回はこのことについてと修正後のパフォーマンスについて書いていきたいと思います!

修正してもらうきっかけ

普段通りTwitterでくだらないことを呟いていたのですが、そしたら急に外国人(Williamsさん)からこのようなリプライが送られてきました〜

実際私も作ってる時にパフォーマンスが課題だと思っていました。ですが、async-httpを使うと高速化できるとということで実際に修正をお願いしました! ネット上の外国人とコミュニケーション取ることがまずない私は結構おどおどしながら返信してました…w

修正内容

こちらがWilliamsさんが作成してくれた修正プルリクエストです! 私のコードはごっそり変更されていますね…w

私も今コードを読んで理解しようとはしているものの、まだパッとしないのが現状です… もうちょっとRuby勉強しないとなぁ…

Williamsさんも親切に私にわかりやすくするためにコメントを書いてくださったのでそれを読みながら以下のコメントを付け足しました… 私の解釈なので間違ってたら指摘してください!!

class Server < Async::DNS::Server
  def initialize(*)
    super
    
    # This will cache one or more open connections.
    # async-httpでコネクションプーリング? KeepAlive?
    @endpoint = Async::HTTP::URLEndpoint.parse("https://cloudflare-dns.com/dns-query")
    @client = Async::HTTP::Client.new(@endpoint)
  end
  
  def process(name, resource_class, transaction)
    type = resource_class.to_s
    type.slice!(0..26)
    
    # This generates the appropriate request URL:
    # URLの生成 ここでは必要なGETクエリーを生成しております〜
    reference = Async::HTTP::Reference.parse(@endpoint.url.path, {
      ct: 'application/dns-json',
      name: name,
      type: type,
    })
    
    # レスポンスを取得
    response = @client.get(reference)
    answers = JSON.parse(response.read)['Answer']
    
    if answers.any?
      transaction.append_question!
      
      answers.each do |answer|
        # DNSのタイプを識別するClassを取得
        if klass = Resolv::DNS::Resource.get_class(answer["type"], resource_class::ClassValue)
          # 全くわからん()
          if klass < Resolv::DNS::Resource::DomainName
            resource = klass.new(Resolv::DNS::Name.create(answer["data"]))
          else
            resource = klass.new(answer["data"])
          end
          
          transaction.response.add_answer(answer["name"], answer["TTL"], resource)
        end
      end
    else
      # 回答がない場合はNXDomainを投げる
      transaction.fail!(:NXDomain)
    end
  end
end

async-httpとasync-dnsによりRubyでも並列処理を可能にして、高速に処理しているとうい感じです。

ベンチマークを取ってみたのだが…

私の環境が悪いのか、プログラムのミスなのか、ちゃんと調べていませんが、namebenchを使って計測したらタイムアウトを連発して計測どころではありませんでした…

私のほうで手直ししてから取り直しますね

感想的なまとめ

今回は私自身初めてなことだったので、このような形で記事として残しておきました! 自分もまだまだプログラミング経験浅いのでこれから頑張らなきゃ…

外部の人に手直ししてもらうのはとても嬉しいのですが、書いてもらったコードを理解し、吸収するまでしないと意味がないので、頑張って吸収します〜

私はやっていませんが、わからないところがあったらガンガン聞いたほうがいいかもしれませんねw それでは次の記事で会いましょう!

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください