企业网站一般包括哪些内容,WordPress使用百度分享插件,网站网页设计如何选,南京已经开始二次感染了1、需求分析
一些恶意用户#xff08;可能是黑客、爬虫、DDoS 攻击者#xff09;可能频繁请求服务器资源#xff0c;导致资源占用过高。针对这种问题#xff0c;可以通过IP 封禁#xff0c;可以有效拉黑攻击者#xff0c;防止资源被滥用#xff0c;保障合法…1、需求分析
一些恶意用户可能是黑客、爬虫、DDoS 攻击者可能频繁请求服务器资源导致资源占用过高。针对这种问题可以通过IP 封禁可以有效拉黑攻击者防止资源被滥用保障合法用户的正常访问
2、Nacos 配置管理的核心概念
1、Namespace命名空间
命名空间用于隔离不同的配置集。它允许在同一个 Nacos 集群中将不同的环境如开发、测试、生产或者不同的业务线的配置进行隔离。默认提供了一个 public 命名空间
使用场景在多租户系统中或者需要区分不同的环境时可以使用命名空间。例如开发环境的配置和生产环境的配置完全隔离可以通过不同的命名空间来管理。
2、Group组
配置组是用于将多个相关的配置项进行分类管理的逻辑分组机制。每个配置项可以属于不同的组以便于配置管理。
使用场景当一个应用有多个模块且不同模块之间共享部分配置时可以用组来对这些模块的配置进行分类和管理。例如一个系统中的“支付服务”和“订单服务”可能需要用不同的组来存储各自的配置。
3、Data ID
Data ID 是一个唯一的配置标识符通常与具体的应用程序相关。通过 Data IDNacos 知道如何获取特定应用的某个具体配置。
使用场景每个应用的配置都会有一个独特的 Data ID。例如一个支付系统可能有一个配置文件叫 com.payment.pay-service.yaml这就是它的 Data ID。
4、Config Listener配置监听器
配置监听器用于让客户端实时监听 Nacos 配置中心中的配置变化可以自动感知配置的更新并做出相应的处理
使用场景在需要动态调整配置的场景下使用例如调整缓存大小、切换不同的服务端点等应用可以通过监听器及时感知这些变化并应用新的配置
3、创建黑名单过滤工具类
InterviewPal 项目 已经使用了 Hutool 工具库就用其自带的 BitMapBloomFilter 即可。
Slf4j
public class BlackIpUtils {private static BitMapBloomFilter bloomFilter;// 判断 ip 是否在黑名单内public static boolean isBlackIp(String ip) {return bloomFilter.contains(ip);}// 重建 ip 黑名单public static void rebuildBlackIp(String configInfo) {if (StrUtil.isBlank(configInfo)) {configInfo {};}// 解析 yaml 文件Yaml yaml new Yaml();Map map yaml.loadAs(configInfo, Map.class);// 获取 ip 黑名单ListString blackIpList (ListString) map.get(blackIpList);// 加锁防止并发synchronized (BlackIpUtils.class) {if (CollectionUtil.isNotEmpty(blackIpList)) {// 注意构造参数的设置BitMapBloomFilter bitMapBloomFilter new BitMapBloomFilter(1);for (String ip : blackIpList) {bitMapBloomFilter.add(ip);}bloomFilter bitMapBloomFilter;} else {bloomFilter new BitMapBloomFilter(1);}}}
}
注意
1、synchronized (BlackIpUtils.class) 代表的是这个类的 Class 对象是 JVM 里唯一的、全局唯一的一个对象实例。换句话说这个锁是类级别的锁所有线程只要碰到这把锁都会排队等候不能同时执行里面的代码块。
2、 BitMapBloomFilter bitMapBloomFilter new BitMapBloomFilter(1) 这个构造参数不可以乱传。如何选择适合业务的 k 和 m 值呢幸运的是布隆过滤器有一个可预测的误判率FPP 其中 n 是已经添加元素的数量 k 哈希的次数 m 布隆过滤器的长度如比特数组的大小
极端情况下当布隆过滤器没有空闲空间时满每一次查询都会返回 true 。这也就意味着 m 的选择取决于期望预计添加元素的数量 n 并且 m 需要远远大于 n 。 实际情况中布隆过滤器的长度 m 可以根据给定的误判率FFP的和期望添加的元素个数 n 的通过如下公式计算 3、注意因为 Nacos 配置文件的监听的粒度比较粗只能知晓配置有变更无法知晓是新增、删除还是修改因此不论是选择布隆过滤器还是 HashSet 最方便的处理逻辑就是重建。
4、创建 Nacos 配置监听类
新增监听器代码追求性能的话可以自定义线程池
Slf4j
Component
public class NacosListener implements InitializingBean {NacosInjectedprivate ConfigService configService;Value(${nacos.config.data-id})private String dataId;Value(${nacos.config.group})private String group;Overridepublic void afterPropertiesSet() throws Exception {log.info(nacos 监听器启动);String config configService.getConfigAndSignListener(dataId, group, 3000L, new Listener() {final ThreadFactory threadFactory new ThreadFactory() {private final AtomicInteger poolNumber new AtomicInteger(1);Overridepublic Thread newThread(NotNull Runnable r) {Thread thread new Thread(r);thread.setName(refresh-ThreadPool poolNumber.getAndIncrement());return thread;}};final ExecutorService executorService Executors.newFixedThreadPool(1, threadFactory);// 通过线程池异步处理黑名单变化的逻辑Overridepublic Executor getExecutor() {return executorService;}// 监听后续黑名单变化Overridepublic void receiveConfigInfo(String configInfo) {log.info(监听到配置信息变化{}, configInfo);BlackIpUtils.rebuildBlackIp(configInfo);}});// 初始化黑名单BlackIpUtils.rebuildBlackIp(config);}
}
4.1 详细解读作用
4.1.1、类定义部分
Component让这个类在 Spring 启动时自动加载Slf4j自动注入日志记录器实现了 InitializingBean所以会在 Spring 完成依赖注入后执行 afterPropertiesSet()。
4.1.2、注解部分 Value(${nacos.config.data-id})private String dataId;Value(${nacos.config.group})private String group;这个注解Value(${nacos.config.data-id})的意思就是说读取yml配置文件令dataId interviewPal;
# 配置中心
nacos:config:server-addr: 127.0.0.1:8848 # nacos 地址bootstrap:enable: true # 预加载data-id: interviewPal # 控制台填写的 Data IDgroup: DEFAULT_GROUP # 控制台填写的 grouptype: yaml # 选择的文件格式auto-refresh: true # 开启自动刷新4.1.3、自定义线程工厂
自定义线程池工厂给新建的线程起个名字如refresh-ThreadPool1、refresh-ThreadPool2。
final ThreadFactory threadFactory new ThreadFactory() {private final AtomicInteger poolNumber new AtomicInteger(1);Overridepublic Thread newThread(NotNull Runnable r) {Thread thread new Thread(r);thread.setName(refresh-ThreadPool poolNumber.getAndIncrement());return thread;}};4.1.4、创建线程池
final ExecutorService executorService Executors.newFixedThreadPool(1, threadFactory);用自定义的线程工厂 threadFactory 创建了一个固定大小为1的线程池FixedThreadPool
5、创建黑名单过滤器
黑名单应该对所有请求生效不止是 Controller 的接口所以基于 WebFilter 实现而不是 AOP 切面。WebFilter 的优先级高于 Aspect 切面因为它在整个 Web 请求生命周期中更早进行处理。
请求进入时的顺序
WebFilter首先WebFilter 拦截 HTTP 请求并可以根据逻辑决定是否继续执行请求。Spring AOP切面Aspect如果请求经过过滤器并进入 Spring 管理的 Bean例如 Controller 层此时切面生效对匹配的Bean 方法进行拦截。Controller 层如果 Aspect 没有阻止执行最终请求到达 Controller 或 RestController 的方法。
/*** 全局 IP 黑名单过滤请求拦截器*/
WebFilter(urlPatterns /*, filterName blackIpFilter)
public class BlackIpFilter implements Filter {Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {String ipAddress NetUtils.getIpAddress((HttpServletRequest) servletRequest);if (BlackIpUtils.isBlackIp(ipAddress)) {servletResponse.setContentType(text/json;charsetUTF-8);servletResponse.getWriter().write({\errorCode\:\-1\,\errorMsg\:\黑名单IP禁止访问\});return;}filterChain.doFilter(servletRequest, servletResponse);}}
WebFilter(urlPatterns /*, filterName blackIpFilter)的作用是告诉 Tomcate 这儿有个过滤器名字叫 blackIpFilter它得拦截所有请求/*
6、 ServletComponentScan
最后要在启动类上加上 ServletComponentScan这样过滤器才会被扫描到。