wenmo8 发布的文章

(一) 基本语法 iptables-t filter -A INPUT -p icmp -j DROP 高级语法 iptables-t filter -A INPUT -m mac –mac-source 00:1C:23:3B:2E:B1 -j DROP 区别高级语法与基本语法的不同:首先filter的机制是由iptables_filter.ko模块所提供的功能,而这个模块本身就已提供了一些简单的匹配的过滤方式,而所谓的基本语法是指只使用iptable_filter.ko模块自身所提供的功能。高级语法必须调用其它模块的功能。以高级语法的范例为例,“-mmac”就是告知iptables工具,我们要动用xt_mac.ko模块的功能,由于是调用其它的模块,因此,语法的部分将会随着不同的模块而有所改变,而且每一个模块的语法也不一样,这就是所谓的“高级语法”。 举例1:将222.24.21.195送到本机的ICMP封包丢弃 语法:iptables-A INPUT -p icmp -s 222.24.21.195 -j DROP 语法解释: -AINPUT

保护对象因为本范例所使用的是INPUTChain,故其保护的对象为本机

-picmp

原文-pProtocol(协议)
目的匹配某个特定协议封包,本范例是匹配icmp的封包
语法-p icmp、-ptcp、 -pudp -p all等

-s222.24.21.195

原文-s Source
对应的参数-dDestination
目的匹配封包中“来源”或“目的”端的IP
语法-s222.24.21.195 -s www.baidu.com等,由例子可知,IP位置的表示方法可以用单一IP或标准的CID网段,至于QDN的部分,实际上iptables是把FQDN送至DNS去执行解析,最后加入到规则之中的还是IP

-j

目的JUMP
语法将符合以上两项条件的封包以特定的方式来“处理”

较常见的处理方式:

ACCEPT允许通过
DROP将封包丢弃调,这种处理方式将导致来源端误以为封包丢失,而不断重新发送封包,这个动作将持续到连接Timeout为止
REJECT将封包丢弃掉,并回送一个DestinationUnreachable的ICMP封包给发送端,发送端的应用程序收到这个错误信息封包之后,会终止连接的动作

举例2:不允许222.24.21.195主机通过本机DNS服务来执行名称解析 语法:iptables-A INPUT -p udp -s 222.24.21.195 --dport 53 -j REJECT 语法解释: --dport53

原文--dportDestination Port
对应的参数--sportSource Port
目的匹配TCP、UDP包头中的“来源端Port”或“目的端Port”,这样即可判断连接所要访问的服务,例如:-pudp –dport 53 代表客户端要访问UDP的53port,而UDP的53port就是DNS服务
语法--dport 80、--sport80,但请注意,当时用--dport或--sport参数时,一定要指明是tcp还是udp协议。注意一点:只要规则语法中用到“Port参数”时,一定要加上“-pudp或-ptcp”的参数。

举例3:允许192.168.1.0/24网段的主机对192.168.0.1提出任何的服务请求 语法:iptables-A INPUT -p all -s 192.168.1.0/24 -d 192.168.0.1 -j ACCEPT 语法解释: -pall

目的匹配所有的协议包

-s192.168.1.0/24

目的匹配来源端IP为192.168.1.0/24网段的封包

-jACCEPT

目的开放符合以上3项条件的封包进入

举例4:只允许用户端主机从eth1访问的本机SSH服务 语法: iptables-A INPUT -p tcp -i eth1 --dport 22 -j ACCEPT 语法解释: -ieth1

原文-iin-interface
对应的参数-oout-interface
目的匹配封包的出入接口
语法-i eth1 -oeth2

举例5:不允许本机的应用程序从eth0接口送出封包去访问www.baidu.com网站 语法:iptables-A OUTPUT -o eth0 -p tcp -d www.baidu.com --dport 80 -j REJECT 语法解释: -AOUTPUT

限制的对象因为该例子使用的OUTPUChain,所以目的是限制本机对外的连接

(二) 有上面几个例子了解了iptables的基本语法,下面对参数进行整理总结。 (1)接口的匹配参数

参数名称-i 、-o
参数值参数值会因为防火墙主机所使用的物理接口不同而有所改变,下面列出常见的网络接口名称: * eth0 :以太网络的接口名称。 * ppp0:PPP接口的名称。 * lo :LocalLoopback接口。 * fddi0:光线接口
使用范例-i eth0:匹配从eth0接口送入的封包
意义匹配封包的进出接口
补充可搭配“!”来代表反向,例如,“-i!eth0”即表示匹配不是从eth0接口进入的封包

(2)上层协议(UpperLayer Protocal)的匹配参数

参数名称-p
参数值这些参数会因为匹配的上层协议的不同而有所差异,一般常见的参数如下: * tcp :匹配的上层协议为TCP协议。 * udp :匹配的上层协议为UDP协议。 * icmp :匹配的上层协议为ICMP协议。 * all :匹配所有的上层协议。 关于其它的上层协议可以参考/etc/protocols文档,现在取出一部分内容: ip 0 IP hopopt 0 HOPOPT icmp 1 ICMP igmp 2 IGMP ggp 3 GGP ipencap 4 IP-ENCAP tcp 6 TCP 注:其中第一和第二字段是给系统来使用的,比如说我们写-ptcp还可以写为-p6。因为tcp的代码就是6,第三个字段用于管理员来识别用。

(3)匹配来源/目的的IP地址

参数名称-s -d
参数值来源及目的IP地址匹配,其可接受的IP地址格式如下: *192.168.0.1 :匹配单一IP。 *172.10.0.0/16 :匹配一个Class B的网段。 *192.168.0.0/24 :匹配一个ClassC的网段。 *192.168.0.0/28 :也可以是任何标准CIDR的网段。 * www.qq.com : 也可以是网址,但最后存放到Chain里的值还是IP
使用范例-s192.168.0.1 :匹配从192.168.0.1主机送来的封包 -s192.168.0.0/24 :匹配从192.168.0.0/24网段所送来的封包 -d192.168.0.10 :匹配要送往192.168.0.10主机的封包
意义匹配封包来源或目的IP地址
补充可搭配“!”来代表反向,例如:“-s!192.168.0.0/24”即代表匹配来源端IP不是192.168.0.0/24网段的封包

(4)匹配来源/目的的Port位置

参数名称--sport–dport
参数值我们可以用—sport或—dport来匹配所要访问的服务,例如我们可以用--dport80参数匹配访问WebServer的封包,另外,也可以使用 --sport80参数匹配有WebServer回应给客户端的封包
使用范例--dport 80 :匹配访问的WebServer的封包。 --sport 110:匹配由POP3 Server 回应给客户端的封包。
意义匹配封包来源或目的的Port
补充可以搭配”!“来代表反向,如”--sport! 80“代表匹配不是从WebServer送来的封包

(5)处理方式

参数名称-j
参数值较为常见的3种处理方式,分别如下: * ACCEPT:允许 * DROP :将封包丢弃 * REJECT :将封包丢弃,并回应发送端一个ICMP封包
使用范例-j ACCEPT 允许 -j DROP 将封包丢弃
意义以特定的方式来处理符合条件的封包


在项目中,我们会需要获取接口的操作日志。比如获取接口的接口名、操作人,接口运行时间、所属的服务、接口的类型(增删改查)等等。初级的做法是在接口方法执行完后将这些操作记录存入库中,这段代码写在接口中,但是这样违反了设计原则中的单一职责原则。常用的做法是使用AOP来做,在运行时动态的插入日志记录的代码。这里我是用注解来做。

创建日志记录表

首先我们来创建日志记录表:


operation表

当然后编写实体类:


编写日志记录注解

我们先定义一个注解OperationLog


这个注解里面定义了几个参数:

opType:业务类型

opBusinessName:业务名称,例如会员服务、订单服务等等

opBusinessId:业务来源ID,一般为主键ID

定义业务类型类OperationType


这个业务类型类定义了接口的类型:增删改查。

接下来我们编写切面类OperationLogAspect

获取方法上面的注解:

Method method = ((MethodSignature) pjp.getSignature()).getMethod();//获取目标方法上面的注解OperationLog opLog = method.getAnnotation(OperationLog.class);

执行目标方法:

try {    // 执行目标方法    result = pjp.proceed();} catch (Throwable throwable) {    throw new Exception(throwable);}

在执行目标方法前后记录执行时间:

TimeInterval timer = DateUtil.timer();... // 执行目标方法...long executeTime = timer.intervalRestart(); 

解析注解上的表达式,就是获取业务id:

// 解析表达式,获取结果String itemId = String.valueOf(expression.getValue(context));

将数据封装到对象中:

Operation operation = Operation.builder()                    //.id(snowflake.nextId())                    .opType(opLog.opType().name())                    .opBusinessName(opLog.opBusinessName())                    .opBusinessId(itemId)                    .opTime(String.valueOf(executeTime))                    //这里可以添加操作人                    .build();

记录日志并入库:

private void handle(Operation operation) {    // 通过日志打印输出    log.info("opType = " + operation.getOpType() + ",opItem = " + operation.getOpBusinessName() + ",opItemId = " + operation.getOpBusinessId() + ",opTime = " + operation.getOpTime());    // 持久化入库    operationService.save(operation);}

整体代码如下:


测试注解

测试注解代码如下:

@RequestMapping("/getById")@ResponseBody@OperationLog(opType = OperationType.QUERY,opBusinessName = "会员服务",opBusinessId = "#id")public Member getById(@RequestParam String id) {    return memberService.getById(id);}

我们在这个接口getById上添加了注解@OperationLog,表明我们想记录这个接口的操作记录。opType为查询类型,所属的业务为会员服务,业务id为接口的参数id。

启动代码运行接口:


控制台打印了日志:


并且数据库也有了记录:


代码到这里就结束了,当然我们还可以在日志记录表中添加接口名的路径、以及接口的调用链等信息。

限流算法目前程序开636f70793231313335323631343130323136353331333433663032发过程常用的限流算法有两个:漏桶算法和令牌桶算法。

漏桶算法

漏桶算法的原理比较简单,请求进入到漏桶中,漏桶以一定的速率漏水。当请求过多时,水直接溢出。可以看出,漏桶算法可以强制限制数据的传输速度。如图所示,把请求比作是水滴,水先滴到桶里,通过漏洞并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。


图片来自网络

漏桶的出水速度是恒定的,那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。

令牌桶算法

令牌桶算法的原理是系统以一定速率向桶中放入令牌,如果有请求时,请求会从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务。这种算法可以应对突发程度的请求,因此比漏桶算法好。


图片来自网络

漏桶算法和令牌桶算法的选择

两者的主要区别漏桶算法能够强行限制处理数据的速率,不论系统是否空闲。而令牌桶算法能够在限制数据的平均处理速率的同时还允许某种程度的突发流量。如何理解上面的含义呢?漏桶算法,比如系统吞吐量是 120/s,业务请求 130/s,使用漏斗限流 100/s,起到限流的作用,多余的请求将产生等待或者丢弃。对于令牌桶算法,每秒产生 100 个令牌,系统容量 200 个令牌。正常情况下,业务请求 100/s 时,请求能被正常被处理。当有突发流量过来比如 200 个请求时,因为系统容量有 200 个令牌可以同一时刻处理掉这 200 个请求。如果是漏桶算法,则只能处理 100 个请求,其他的请求等待或者被丢弃。


项目引用了vue.js但是没用脚手架搭建项目,如何让e...其实。不需要,element从来没有说过要用es6的语法。 但是如果你不用,很多功能都需要你对javascript的模块化有很深的了解,感觉还不如去学一下语法,成本会更低。

什么时候不该使用es6箭头函数

想了一下,大概有以下几种情况吧: 不支持箭头函数的环境 目前支持箭头函数的环境毕竟还不多,仅 Safari、Chrome、Firefox 较新版本,Microsoft Edge、NodeJS 4.x、NodeJS 6.x 支持。IE 全系列都不支持。 在函数里面需要使用 this 变量的时候 箭


Babel转换es6怎么支持ie8

用babel转换es6在ie8下报错:在default处报缺少标识符 字符串或数字 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

我是用webpack配置的 test: /\.js/, loader: "babel-loader", que

浏览器怎么使用ES6的Proxy

axios不是支持ie9以上吗?为啥我的ie全挂了


一、VsCode使用 1.1 VsCode基本操作

Alt + Shift + F格式化代码


二、ES6新特性 2.1 let声明常量

2.2 const声明常量(只读变量)

2.3 解析表达式 2.3.1 数组解构

2.3.2 对象解构

2.4 字符串扩展

2.5 函数优化 2.5.1 函数参数的默认值

2.5.2 不定参数

2.5.3 箭头函数

2.5.4 实战:箭头函数结合解构表达式

2.6 对象优化 2.6.1 新增的API

2.6.2 声明对象简写 

2.6.3 对象的函数属性简写

2.6.4 对象扩展运算符

2.7 map和reduce 2.7.1 map

2.7.2 reduce

2.8 promise异步编排

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
    <script>
        //1、 查出当前用户信息
//2、 按照当前用户的id查出他的课程
//3、 按照当前课程id查出分数
$.ajax({
    url: "mock/user.json",
    success(data) {
        console.log("查询用户:", data);
        $.ajax({
            url: `mock/user_corse_${data.id}.json`,
            success(data) {
                console.log("查询到课程:", data);
                $.ajax({
                    url: `mock/corse_score_${data.id}.json`,
                    success(data) {
                        console.log("查询到分数:", data);
                    },
                    error(error) {
                        console.log("出现异常了:" + error);
                    }
                });
            },
            error(error) {
                console.log("出现异常了:" + error);
            }
        });
    },
    error(error) {
        console.log("出现异常了:" + error);
    }
});
//1、Promise可以封装异步操作  
let p = new Promise((resolve, reject) => {
    //1、异步操作  
    $.ajax({
        url: "mock/user.json",
        success: function (data) {
            console.log("查询用户成功:", data) resolve(data);
        },
        error: function (err) {
            reject(err);
        }
    });
});
p.then((obj) => {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: `mock/user_corse_${obj.id}.json`,
            success: function (data) {
                console.log("查询用户课程成功:", data) resolve(data);
            },
            error: function (err) {
                reject(err)
            }
        });
    })
}).then((data) => {
    console.log("上一步的结果", data) $.ajax({
        url: `mock/corse_score_${data.id}.json`,
        success: function (data) {
            console.log("查询课程得分成功:", data)
        },
        error: function (err) { }
    });
})

function get(url, data) {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: url,
            data: data,
            success: function (data) {
                resolve(data);
            },
            error: function (err) {
                reject(err)
            }
        })
    });
}
get("mock/user.json").then((data) => {
    console.log("用户查询成功~~~:", data) return get(`mock/user_corse_${data.id}.json`);
}).then((data) => {
    console.log("课程查询成功~~~:", data) return get(`mock/corse_score_${data.id}.json`);
}).then((data) => {
    console.log("课程成绩查询成功~~~:", data)
}).catch((err) => {
    console.log("出现异常", err)
});
 </script>
</body>

</html>

2.9 模块化