sensitive-word-admin v1.3.0 發佈 如何支持敏感詞控台分散式部署?

来源:https://www.cnblogs.com/houbbBlogs/p/18019891
-Advertisement-
Play Games

拓展閱讀 sensitive-word-admin v1.3.0 發佈 如何支持分散式部署? sensitive-word-admin 敏感詞控台 v1.2.0 版本開源 sensitive-word 基於 DFA 演算法實現的高性能敏感詞工具介紹 更多技術交流 業務背景 如果我們的敏感詞部署之後,不 ...


拓展閱讀

sensitive-word-admin v1.3.0 發佈 如何支持分散式部署?

sensitive-word-admin 敏感詞控台 v1.2.0 版本開源

sensitive-word 基於 DFA 演算法實現的高性能敏感詞工具介紹

更多技術交流

view

業務背景

如果我們的敏感詞部署之後,不會變化,那麼其實不用考慮這個問題。

但是實際業務,敏感詞總是隨著時間不斷變化的,所以我們需要支持敏感詞的動態修改。

整體設計

pull vs push

以資料庫存儲自定義場景為例,如果頁面修改了敏感詞信息,那麼如何通知到部署的多台敏感詞客戶端呢?

一般通知方式有兩大類:

1)push 推送方式

修改時同時通知敏感詞發生了變化,每個敏感詞客戶端接收到通知後,重新初始化敏感詞信息。

優點是實時性比較高,缺點是需要引入額外的通知機制,需要通知的服務比較多時,也比較麻煩。

推送方式

2)pull 拉取方式

修改後,直接落庫資料庫,每一個敏感詞客戶端自己定時拉取變更的信息。

這種方式有點是非常簡單,缺點是存在一定的延遲性。

定時拉取

考慮到我們的場景可以允許分鐘級的延遲,所以這裡先實現定時拉取方式。

如何知道敏感詞是否發生了變化?

定時拉取的方式比較簡單,但是每一次拉取的話,如何知道是否需要重新初始化呢?

雖然每次的初始化的耗時還好,但是考慮到變更不是很頻繁,所以有沒有辦法定時拉取時知道有沒有變化呢?

回顧一下上一篇文章,我們設計的 word 表

create table word
(
    id int unsigned auto_increment comment '應用自增主鍵' primary key,
    word varchar(128) not null comment '單詞',
    type varchar(8) not null comment '類型',
    status char(1) not null default 'S' comment '狀態',
    remark varchar(64) not null comment '配置描述' default '',
    operator_id varchar(64) not null default 'system' comment '操作員名稱',
    create_time timestamp default CURRENT_TIMESTAMP not null comment '創建時間戳',
    update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新時間戳'
) comment '敏感詞表' ENGINE=Innodb default charset=UTF8 auto_increment=1;
create unique index uk_word on word (word) comment '唯一索引';

根據更新時間可以嗎?

如果我們所有的數據都不執行物理刪除,那麼直接根據 word 表的 update_time 即可判斷。

但是如果一個數據真的被刪除了,那麼這種方式就不行了。

delete 的數據怎麼辦?

如果我們期望執行物理刪除的話,那隻有添加對應的日誌表。

我們可以通過日誌表的 update_time 來處理。

操作日誌表

v1.2.0 的表設計

回顧一下 v1.2.0 表設計,如下:

create table word_log
(
    id int unsigned auto_increment comment '應用自增主鍵' primary key,
    batch_id varchar(128) not null comment '批次號',
    word varchar(128) not null comment '單詞',
    type varchar(8) not null comment '類型',
    status char(1) not null default 'S' comment '單詞狀態。S:啟用;F:禁用',
    remark varchar(64) not null comment '配置描述' default '',
    operator_id varchar(64) not null default 'system' comment '操作員名稱',
    create_time timestamp default CURRENT_TIMESTAMP not null comment '創建時間戳',
    update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新時間戳'
) comment '敏感詞操作日誌表' ENGINE=Innodb default charset=UTF8 auto_increment=1;
create index ix_word on word_log (word) comment '單詞普通索引';
create index ix_batch_id on word_log (batch_id) comment '批次號普通索引';

枚舉:

insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'status', 'S', '正常');
insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'status', 'F', '失效');

insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'type', 'ALLOW', '允許');
insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'type', 'DENY', '禁止');

表結構調整

我們對原來的表做一點調整。

調整後的建表語句

考慮到後續 sensitive-word 可能做精確的單個單詞變化處理,我們最好可以知道每一次詞內容的具體變化。

word 敏感詞主題
word_before 變更前的單詞
word_after 變更後的單詞

調整後的建表語句:

drop table word_log;

create table word_log
(
    id int unsigned auto_increment comment '應用自增主鍵' primary key,
    batch_id varchar(128) not null comment '批次號',
    word varchar(128) not null comment '單詞',
    word_before varchar(128) null comment '變更前單詞',
    word_after varchar(128) null comment '變更後單詞',
    type varchar(8) not null comment '類型',
    status char(1) not null default 'S' comment '單詞狀態',
    remark varchar(64) not null comment '配置描述' default '',
    operator_type varchar(16) not null default '' comment '操作類別',
    operator_id varchar(64) not null default 'system' comment '操作員名稱',
    create_time timestamp default CURRENT_TIMESTAMP not null comment '創建時間戳',
    update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新時間戳'
) comment '敏感詞操作日誌表' ENGINE=Innodb default charset=UTF8 auto_increment=1;
create index ix_word on word_log (word) comment '單詞普通索引';
create index ix_batch_id on word_log (batch_id) comment '批次號普通索引';
create index ix_update_time on word_log (update_time) comment '更新時間普通索引';

添加操作類別(operator_type):

insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'operator_type', 'CREATE', '新增');
insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'operator_type', 'DELETE', '刪除');
insert into lc_enum_mapping (table_name, column_name, `key`, label)  values ('word_log', 'operator_type', 'UPDATE', '更新');

例子

1)新增

新增 '敏感'

word 敏感
word_before null
word_after 敏感

2)修改

修改 '敏感',到 '敏感修改'

word 敏感
word_before 敏感
word_after 敏感修改
  1. 刪除

刪除 '敏感修改'

word 敏感修改
word_before 敏感修改
word_after null

刷新核心邏輯

我們啟動一個定時任務,判斷存在更新時,則重新初始化對應的敏感詞信息。

package com.github.houbb.sensitive.word.admin.web.config;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.github.houbb.heaven.util.util.DateUtil;
import com.github.houbb.sensitive.word.admin.dal.entity.WordLog;
import com.github.houbb.sensitive.word.admin.service.service.WordLogService;
import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 分散式部署的更新問題:
 *
 * 模式1:push
 * 實時性好,但是需要感知系統的存在。
 *
 * 模式2:pull
 * 存在延遲,但是無狀態,簡單。
 *
 * 這裡採用模式2
 *
 * @since 1.2.0
 */
@Component
@Slf4j
public class MySensitiveWordScheduleRefresh {

    private static final Logger logger = LoggerFactory.getLogger(MySensitiveWordScheduleRefresh.class);

    @Autowired
    private SensitiveWordBs sensitiveWordBs;

    @Autowired
    private WordLogService wordLogService;

    /**
     * 刷新時間間隔
     * @since 1.3.0
     */
    @Value("${sensitive-word.refresh-interval-seconds}")
    private int refreshIntervalSeconds;

    @PostConstruct
    public void init() {
        logger.info("MySensitiveWordScheduleRefresh init with refreshIntervalSeconds={}", refreshIntervalSeconds);

        // 單線程定時調度。
        // TODO: 調整對應的 word_log 實現
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    logger.info("MySensitiveWordScheduleRefresh start");

                    refresh();

                    logger.info("MySensitiveWordScheduleRefresh end");
                } catch (Exception e) {
                    logger.error("MySensitiveWordScheduleRefresh meet ex", e);
                }
            }
        }, refreshIntervalSeconds, refreshIntervalSeconds, TimeUnit.SECONDS);
    }

    /**
     * 更新詞庫
     *
     * 每次資料庫的信息發生變化之後,首先調用更新資料庫敏感詞庫的方法。
     * 如果需要生效,則調用這個方法。
     *
     * 說明:重新初始化不影響舊的方法使用。初始化完成後,會以新的為準。
     */
    private void refresh() {
        // 延長10S,避免遺漏
        int timeDiffer = refreshIntervalSeconds + 10;
        // 判斷當前一段時間內是否存在變化?
        Date date = DateUtil.addSecond(new Date(), -timeDiffer);

        Wrapper<WordLog> wordLogWrapper = new EntityWrapper<>();
        wordLogWrapper.gt("update_time", date);
        int count = wordLogService.selectCount(wordLogWrapper);
        if(count <= 0) {
            logger.info("MySensitiveWordScheduleRefresh 沒有新增的變化信息,忽略更新。");
            return;
        }

        // 每次資料庫的信息發生變化之後,首先調用更新資料庫敏感詞庫的方法,然後調用這個方法。
        // 後續可以優化為針對變化的初始化。
        sensitiveWordBs.init();
    }
    
}

sensitive-word.refresh-interval-seconds 屬性指定了刷新的間隔,可配置。

小結

分散式環境下還是儘可能的追求架構的簡潔性,這裡只是一種實現的方式,也可以自己實現基於 push 的模式。

開源代碼

sensitive-word-admin v1.3.0

參考資料

https://github.com/houbb/sensitive-word-admin

本文由博客一文多發平臺 OpenWrite 發佈!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ServerCnxnFactory 用於接收客戶端連接、管理客戶端session、處理客戶端請求。 ServerCnxn抽象類 代表一個客戶端連接對象: 從網路讀寫數據 數據編解碼 將請求轉發給上層組件或者從上層組件接收響應 管理連接狀態,比如:enableRecv、sessionTimeout、s ...
  • 本文深入介紹了Java 8的Stream API,包括創建、中間操作、終端操作等,強調了並行流在大數據處理中的性能提升。提供清晰實用的示例,為讀者理解流式計算提供有益指導。 ...
  • 在之前的文章中,我們簡單的介紹了線程誕生的意義和基本概念,採用多線程的編程方式,能充分利用 CPU 資源,顯著的提升程式的執行效率。其中java.lang.Thread是 Java 實現多線程編程最核心的類,學習Thread類中的方法,是學習多線程的第一步。 ...
  • 今天我們主要講解的是Spring依賴註入。在本文中,我們主要圍繞bean填充屬性的欄位和setter方法展開討論。要記住的是,在進行屬性註入時,我們首先需要找到註入點併進行緩存,然後才會真正進行屬性註入。需要註意的是,靜態欄位或方法是不會進行依賴註入的。最後,我們簡單地介紹了一下關鍵源碼,以及對@R... ...
  • 通過`FromStr`及`Display`的重定義,我們可以支持更強大的自定義的序列化操作,系統綁定埠既認埠號也認綁定IP,所以我們可以對同個埠進行多次綁定。 ...
  • python打包和反編譯 從py到exe 打包 安裝Pyinstaller pip install pyinstaller //太慢可切源 pip install -i https://pypi.douban.com/simple/ pyinstaller #豆瓣源 pip install -i h ...
  • API介面是一種讓不同系統之間實現數據交互的工具,它可以實現不同系統之間的數據共用和數據傳遞。全國今日油價API介面是一項非常有用的介面,它可以提供最新的全國各省汽油和柴油價格信息。本文將為大家介紹全國今日油價API介面的使用方法,並提供相應代碼說明。 介面名稱:全國今日油價API介面介面地址:ht ...
  • 當我們在編寫代碼時,經常會遇到需要管理資源的情況,比如打開和關閉文件,如果遇到了一些異常情況,我們需要關閉資源,不然會導致資源泄露,雖然我們可以通過手動的方式來關閉,但如果有多個異常情況需要考慮的話,萬一不小心漏了一處,就芭比Q了。所以,如果有一種更加優雅的方式來處理資源泄露的問題,那必定是非常ni ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...