mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00
perf: 使用单例模式消除重复协议检测
核心修复: - 将WebPortDetector改为全局单例,消除多实例问题 - 所有协议检测共享同一个缓存,避免重复TCP连接 - 使用sync.Once确保线程安全的单例初始化 性能提升: - 每个端口的协议检测从多次减少到1次 - 大幅降低TCP连接数,减少网络开销 - 缓存命中率显著提升 技术实现: - GetWebPortDetector() 替代 NewWebPortDetector() - newWebPortDetector() 改为私有方法 - BaseScanStrategy统一使用单例实例 这是数据结构决定性能的经典案例 - 通过正确的实例管理 彻底解决了重复检测问题
This commit is contained in:
parent
57aa48be58
commit
9ad397f58f
@ -194,15 +194,15 @@ func (b *BaseScanStrategy) isLocalPlugin(pluginName string) bool {
|
|||||||
|
|
||||||
// isWebServicePort 使用智能检测判断端口是否运行Web服务(含预定义端口)
|
// isWebServicePort 使用智能检测判断端口是否运行Web服务(含预定义端口)
|
||||||
func (b *BaseScanStrategy) isWebServicePort(host string, port int) bool {
|
func (b *BaseScanStrategy) isWebServicePort(host string, port int) bool {
|
||||||
// 创建Web端口检测器实例
|
// 使用全局单例Web端口检测器
|
||||||
detector := NewWebPortDetector()
|
detector := GetWebPortDetector()
|
||||||
return detector.IsWebService(host, port)
|
return detector.IsWebService(host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isWebServicePortByProtocol 仅通过HTTP协议检测判断端口是否运行Web服务(不使用预定义端口列表)
|
// isWebServicePortByProtocol 仅通过HTTP协议检测判断端口是否运行Web服务(不使用预定义端口列表)
|
||||||
func (b *BaseScanStrategy) isWebServicePortByProtocol(host string, port int) bool {
|
func (b *BaseScanStrategy) isWebServicePortByProtocol(host string, port int) bool {
|
||||||
// 创建Web端口检测器实例
|
// 使用全局单例Web端口检测器
|
||||||
detector := NewWebPortDetector()
|
detector := GetWebPortDetector()
|
||||||
// 直接调用协议检测,跳过预定义端口检查
|
// 直接调用协议检测,跳过预定义端口检查
|
||||||
return detector.DetectHTTPServiceOnly(host, port)
|
return detector.DetectHTTPServiceOnly(host, port)
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,28 @@ type WebPortDetector struct {
|
|||||||
httpsClient *http.Client
|
httpsClient *http.Client
|
||||||
// 检测结果缓存(避免重复检测)
|
// 检测结果缓存(避免重复检测)
|
||||||
detectionCache map[string]bool
|
detectionCache map[string]bool
|
||||||
|
// 协议检测缓存(避免重复TCP连接)
|
||||||
|
protocolCache map[string]bool
|
||||||
// 缓存互斥锁
|
// 缓存互斥锁
|
||||||
cacheMutex sync.RWMutex
|
cacheMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebPortDetector 创建Web端口检测器
|
var (
|
||||||
func NewWebPortDetector() *WebPortDetector {
|
// 全局单例实例
|
||||||
|
webDetectorInstance *WebPortDetector
|
||||||
|
webDetectorOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetWebPortDetector 获取Web端口检测器单例
|
||||||
|
func GetWebPortDetector() *WebPortDetector {
|
||||||
|
webDetectorOnce.Do(func() {
|
||||||
|
webDetectorInstance = newWebPortDetector()
|
||||||
|
})
|
||||||
|
return webDetectorInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWebPortDetector 创建Web端口检测器(私有方法)
|
||||||
|
func newWebPortDetector() *WebPortDetector {
|
||||||
timeout := 3 * time.Second
|
timeout := 3 * time.Second
|
||||||
|
|
||||||
// 只保留最基本的Web端口用于快速路径优化
|
// 只保留最基本的Web端口用于快速路径优化
|
||||||
@ -82,6 +98,7 @@ func NewWebPortDetector() *WebPortDetector {
|
|||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
httpsClient: httpsClient,
|
httpsClient: httpsClient,
|
||||||
detectionCache: make(map[string]bool),
|
detectionCache: make(map[string]bool),
|
||||||
|
protocolCache: make(map[string]bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,6 +367,28 @@ func (w *WebPortDetector) isNonWebHTTPService(serverHeader, contentType string)
|
|||||||
|
|
||||||
// quickProtocolCheck 快速协议检查,避免向非HTTP服务发送HTTP请求
|
// quickProtocolCheck 快速协议检查,避免向非HTTP服务发送HTTP请求
|
||||||
func (w *WebPortDetector) quickProtocolCheck(ctx context.Context, host string, port int) bool {
|
func (w *WebPortDetector) quickProtocolCheck(ctx context.Context, host string, port int) bool {
|
||||||
|
// 检查协议缓存
|
||||||
|
protocolKey := fmt.Sprintf("%s:%d:protocol", host, port)
|
||||||
|
w.cacheMutex.RLock()
|
||||||
|
if cached, exists := w.protocolCache[protocolKey]; exists {
|
||||||
|
w.cacheMutex.RUnlock()
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
w.cacheMutex.RUnlock()
|
||||||
|
|
||||||
|
// 执行实际的协议检测
|
||||||
|
result := w.doProtocolCheck(ctx, host, port)
|
||||||
|
|
||||||
|
// 缓存结果
|
||||||
|
w.cacheMutex.Lock()
|
||||||
|
w.protocolCache[protocolKey] = result
|
||||||
|
w.cacheMutex.Unlock()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// doProtocolCheck 执行实际的协议检测
|
||||||
|
func (w *WebPortDetector) doProtocolCheck(ctx context.Context, host string, port int) bool {
|
||||||
// 建立TCP连接
|
// 建立TCP连接
|
||||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 2*time.Second)
|
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 2*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
BIN
fscan-lite/main.o
Normal file
BIN
fscan-lite/main.o
Normal file
Binary file not shown.
BIN
fscan-lite/platform.o
Normal file
BIN
fscan-lite/platform.o
Normal file
Binary file not shown.
BIN
fscan-lite/scanner.o
Normal file
BIN
fscan-lite/scanner.o
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user