mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +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服务(含预定义端口)
|
||||
func (b *BaseScanStrategy) isWebServicePort(host string, port int) bool {
|
||||
// 创建Web端口检测器实例
|
||||
detector := NewWebPortDetector()
|
||||
// 使用全局单例Web端口检测器
|
||||
detector := GetWebPortDetector()
|
||||
return detector.IsWebService(host, port)
|
||||
}
|
||||
|
||||
// isWebServicePortByProtocol 仅通过HTTP协议检测判断端口是否运行Web服务(不使用预定义端口列表)
|
||||
func (b *BaseScanStrategy) isWebServicePortByProtocol(host string, port int) bool {
|
||||
// 创建Web端口检测器实例
|
||||
detector := NewWebPortDetector()
|
||||
// 使用全局单例Web端口检测器
|
||||
detector := GetWebPortDetector()
|
||||
// 直接调用协议检测,跳过预定义端口检查
|
||||
return detector.DetectHTTPServiceOnly(host, port)
|
||||
}
|
||||
|
@ -25,12 +25,28 @@ type WebPortDetector struct {
|
||||
httpsClient *http.Client
|
||||
// 检测结果缓存(避免重复检测)
|
||||
detectionCache map[string]bool
|
||||
// 协议检测缓存(避免重复TCP连接)
|
||||
protocolCache map[string]bool
|
||||
// 缓存互斥锁
|
||||
cacheMutex sync.RWMutex
|
||||
}
|
||||
|
||||
// NewWebPortDetector 创建Web端口检测器
|
||||
func NewWebPortDetector() *WebPortDetector {
|
||||
var (
|
||||
// 全局单例实例
|
||||
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
|
||||
|
||||
// 只保留最基本的Web端口用于快速路径优化
|
||||
@ -82,6 +98,7 @@ func NewWebPortDetector() *WebPortDetector {
|
||||
httpClient: httpClient,
|
||||
httpsClient: httpsClient,
|
||||
detectionCache: make(map[string]bool),
|
||||
protocolCache: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,6 +367,28 @@ func (w *WebPortDetector) isNonWebHTTPService(serverHeader, contentType string)
|
||||
|
||||
// quickProtocolCheck 快速协议检查,避免向非HTTP服务发送HTTP请求
|
||||
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连接
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 2*time.Second)
|
||||
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