CoreDNS粗解( 三 )


// 创建server对象并启动// 这里的context来自corednsserverregister.goslist, err := inst.context.MakeServers()err = startServers(slist, inst, restartFds)MakeServers代码如下:
func (h *dnsContext) MakeServers() ([]caddy.Server, error) { // 检查配置文件是否有冲突, 比如监听域名是否有重复等 errValid := h.validateZonesAndListeningAddresses() // 共享第一个配置的相关值 for _, c := range h.configs {c.Plugin = c.firstConfigInBlock.Pluginc.ListenHosts = c.firstConfigInBlock.ListenHostsc.Debug = c.firstConfigInBlock.Debugc.TLSConfig = c.firstConfigInBlock.TLSConfig } // 将监听的端口聚合起来 groups, err := groupConfigsByListenAddr(h.configs)// 开始创建caddy.Server var servers []caddy.Server for addr, group := range groups {// switch on addrswitch tr, _ := parse.Transport(addr); tr {// 默认就是DNScase transport.DNS:s, err := NewServer(addr, group)if err != nil {return nil, err}servers = append(servers, s)// 还有TLS,GRPC,HTTPS } return servers, nil}func NewServer(addr string, group []*Config) (*Server, error) { s := &Server{Addr:addr,zones:make(map[string]*Config),graceTimeout: 5 * time.Second, }// 为每个zone构建一个site对象以及对应的stack对象, 并注册各指令 , 然后赋值pluginChain// pluginChain就是后面的响应函数 for _, site := range group {if site.Debug {s.debug = truelog.D.Set()}s.zones[site.Zone] = sitevar stack plugin.Handler// 将插件列表按倒叙依次传给优先级高的插件// 这样一层套一层就可以让优先级高的插件在最外层 , 也就是优先执行 。for i := len(site.Plugin) - 1; i >= 0; i-- {stack = site.Plugin[i](stack)site.registerHandler(stack)}}site.pluginChain = stack } return s, nil}至此构造好了配置文件中的各个Server对象 , 然后开始监听服务
startServers代码如下:
func startServers(serverList []Server, inst *Instance, restartFds map[string]restartTriple) error { for _, s := range serverList {var (ln .NET.Listenerpcnet.PacketConnerr error)// 可以看到默认tcp和udp同时监听if ln == nil {ln, err = s.Listen()if err != nil {return fmt.Errorf("Listen: %v", err)}}if pc == nil {pc, err = s.ListenPacket()if err != nil {return fmt.Errorf("ListenPacket: %v", err)}}inst.servers = append(inst.servers, ServerListener{server: s, listener: ln, packet: pc}) }// 一起启动监听服务// tcp接口调用Serve// udp接口调用ServePacket for _, s := range inst.servers {inst.wg.Add(2)stopWg.Add(2)func(s Server, ln net.Listener, pc net.PacketConn, inst *Instance) {go func() {defer func() {inst.wg.Done()stopWg.Done()}()errChan <- s.Serve(ln)}()go func() {defer func() {inst.wg.Done()stopWg.Done()}()errChan <- s.ServePacket(pc)}()}(s.server, s.listener, s.packet, inst) } return nil}至此监听服务启动起来了 , 可以接口客户端的请求 。
这里看看udp的处理逻辑把
// corednsserverserver.gofunc (s *Server) ServePacket(p net.PacketConn) error { s.m.Lock()// 这里的Handler实现了ServeDNS接口, 会直接动用传入的函数 s.server[udp] = &dns.Server{PacketConn: p, Net: "udp", Handler: dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) {ctx := context.WithValue(context.Background(), Key{}, s)ctx = context.WithValue(ctx, LoopKey{}, 0)// ServeDNS是每个插件都要实现的函数接口, 超级重要的流量入口// 最终将数据导向h.pluginChain.ServeDNSs.ServeDNS(ctx, w, r) })} s.m.Unlock() return s.server[udp].ActivateAndServe()}// 后面的调用链比较长 , 大家了解一下就行 , 其实最终还是调用上面的HandlerFunc里面传入的匿名函数func (srv *Server) ActivateAndServe() error { srv.init() if srv.PacketConn != nil {srv.started = trueunlock()return srv.serveUDP(srv.PacketConn) } return &Error{err: "bad listeners"}}func (srv *Server) serveUDP(l net.PacketConn) error { defer l.Close() reader := Reader(defaultReader{srv}) lUDP, isUDP := l.(*net.UDPConn) readerPC, canPacketConn := reader.(PacketConnReader) rtimeout := srv.getReadTimeout() // 不断读取udp包 for srv.isStarted() {var (m[]bytesPCnet.AddrsUDP *SessionUDPerrerror)if isUDP {m, sUDP, err = reader.ReadUDP(lUDP, rtimeout)} else {m, sPC, err = readerPC.ReadPacketConn(l, rtimeout)}wg.Add(1)// 每个包创建一个协程专门处理go srv.serveUDPPacket(&wg, m, l, sUDP, sPC) } return nil}func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) { w := &response{tsigProvider: srv.tsigProvider(), udp: u, udpSession: udpSession, pcSession: pcSession} srv.serveDNS(m, w) wg.Done()}func (srv *Server) serveDNS(m []byte, w *response) {// udp包解析 dh, off, err := unpackMsgHdr(m, 0) req := new(Msg) req.setHdr(dh) switch action := srv.MsgAcceptFunc(dh); action { case MsgAccept:// 处理细节 case MsgReject, MsgRejectNotImplemented:// 处理细节 case MsgIgnore:// 处理细节 }// 这里就是最上面的那个handlerfunc srv.Handler.ServeDNS(w, req) // Writes back to the client}


推荐阅读