Neutron 对虚拟三层网络的实现是通过其 L3 Agent (neutron-l3-agent)。该 Agent 利用 Linux IP 栈、route 和 iptables 来实现内网内不同网络内的虚机之间的网络流量,以及虚机和外网之间网络流量的路由和转发。为了在同一个Linux 系统上支持可能的 IP 地址空间重叠,它使用了 Linux network namespace 来提供隔离的转发上下文。

namespace技术

每个 netns 拥有独立的 (virtual)network devices, IP addresses, IP routing tables, /proc/net directory, ports 等等

新创建的 netns 默认只包含 loopback device(回环设备)。除了这个设备,每个 network device,不管是物理的还是虚拟的网卡还是网桥等,都只能存在于一个 netns。而且,连接物理硬件的物理设备只能存在于 root netns。其它普通的网络设备可以被创建和添加到某个 netns。

[root@bogon ~]# ip netns add test_namespace
[root@bogon ~]# ip netns
test_namespace
[root@bogon ~]# ip netns list
test_namespace
[root@bogon ~]# ip netns exec test_namespace bash
[root@bogon ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@bogon ~]#

添加 virtual interfaces 到 network namespace

[root@bogon ~]# ip link add veth-a type veth peer name veth-b#创建一对虚拟网卡veth-a 和 veth-b,两者由一根虚拟网线连接
[root@bogon ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:0f:09:89 brd ff:ff:ff:ff:ff:ff
inet 192.168.246.138/24 brd 192.168.246.255 scope global dynamic ens33
valid_lft 1225637sec preferred_lft 1225637sec
inet6 fe80::20c:29ff:fe0f:989/64 scope link
valid_lft forever preferred_lft forever
3: veth-b@veth-a: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 7e:75:c5:5a:70:0b brd ff:ff:ff:ff:ff:ff
4: veth-a@veth-b: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 12:10:96:02:4c:f0 brd ff:ff:ff:ff:ff:ff

将 veth-b 添加到 network namespace

[root@bogon ~]# ip link set veth-b netns netns1
[root@bogon ~]# ip netns exec netns1 bash
[root@bogon ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: veth-b@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 7e:75:c5:5a:70:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@bogon ~]#

Linux下的IP设备已经少了一个

[root@bogon ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:0f:09:89 brd ff:ff:ff:ff:ff:ff
inet 192.168.246.138/24 brd 192.168.246.255 scope global dynamic ens33
valid_lft 1224076sec preferred_lft 1224076sec
inet6 fe80::20c:29ff:fe0f:989/64 scope link
valid_lft forever preferred_lft forever
4: veth-a@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 12:10:96:02:4c:f0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@bogon ~]#

设置namespace的IP地址

[root@bogon ~]# ip addr add 10.0.0.2/24 dev veth-b
[root@bogon ~]# ip link set dev veth-b up
[root@bogon ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: veth-b@if4: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN qlen 1000
link/ether 7e:75:c5:5a:70:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.0.0.2/24 scope global veth-b
valid_lft forever preferred_lft forever
[root@bogon ~]#

设置Linux下的vth-a的IP地址

[root@bogon ~]# ip addr add 10.0.0.1/24 dev veth-a
[root@bogon ~]# ip link set dev veth-a up
[root@bogon ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:0f:09:89 brd ff:ff:ff:ff:ff:ff
inet 192.168.246.138/24 brd 192.168.246.255 scope global dynamic ens33
valid_lft 1223891sec preferred_lft 1223891sec
inet6 fe80::20c:29ff:fe0f:989/64 scope link
valid_lft forever preferred_lft forever
4: veth-a@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 12:10:96:02:4c:f0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.0.0.1/24 scope global veth-a
valid_lft forever preferred_lft forever
inet6 fe80::1010:96ff:fe02:4cf0/64 scope link
valid_lft forever preferred_lft forever
[root@bogon ~]#

ping

[root@bogon ~]# ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.038 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.072 m

查看路由表和IPtables

[root@bogon ~]# ip netns exec netns1 bash
[root@bogon ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 veth-b
[root@bogon ~]# iptables -F
[root@bogon ~]#

Iptables

Neutron 主要用到 filter 表和 nat 表,其中, filter 用来实现安全组(Security Group)和 防火墙(FWaas);nat 主要用来实现 router。

INPUT

可见在INPUT接受所有的数据包

[root@node-3 ~]# iptables  --line-numbers -vnL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-l3-agent-INPUT all -- * * 0.0.0.0/0 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-INPUT
Chain neutron-l3-agent-INPUT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x1/0xffff
2 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8775
[root@node-3 ~]#

OUTPUT

[root@node-3 ~]# iptables --line-numbers -vnL OUTPUT
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-filter-top all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 neutron-l3-agent-OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-filter-top
Chain neutron-filter-top (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-l3-agent-local all -- * * 0.0.0.0/0 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-local
Chain neutron-l3-agent-local (1 references)
num pkts bytes target prot opt in out source destination
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-OUTPUT
Chain neutron-l3-agent-OUTPUT (1 references)
num pkts bytes target prot opt in out source destination
[root@node-3 ~]#

OUTPUT链没有什么规则

FORWARD

[root@node-3 ~]# iptables --line-numbers -vnL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-filter-top all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 neutron-l3-agent-FORWARD all -- * * 0.0.0.0/0 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-filter-top
Chain neutron-filter-top (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-l3-agent-local all -- * * 0.0.0.0/0 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-local
Chain neutron-l3-agent-local (1 references)
num pkts bytes target prot opt in out source destination
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-FORWARD
Chain neutron-l3-agent-FORWARD (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 neutron-l3-agent-iv4a7700495 all -- * qr-+ 0.0.0.0/0 0.0.0.0/0
2 0 0 neutron-l3-agent-ov4a7700495 all -- qr-+ * 0.0.0.0/0 0.0.0.0/0
3 0 0 neutron-l3-agent-fwaas-defau all -- * qr-+ 0.0.0.0/0 0.0.0.0/0
4 0 0 neutron-l3-agent-fwaas-defau all -- qr-+ * 0.0.0.0/0 0.0.0.0/0 在之前没有创建防火墙规则之前只有neutron-l3-agent-fwaas-defau两条规则 一进一出 [root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-iv4a7700495
Chain neutron-l3-agent-iv4a7700495 (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
2 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 0 0 DROP tcp -- * * 2.2.2.0/24 3.3.3.0/24 tcp dpts:1:65535
4 0 0 DROP icmp -- * * 10.0.0.0/24 0.0.0.0/0
[root@node-3 ~]# iptables --line-numbers -vnL neutron-l3-agent-ov4a7700495
Chain neutron-l3-agent-ov4a7700495 (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
2 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 0 0 DROP tcp -- * * 2.2.2.0/24 3.3.3.0/24 tcp dpts:1:65535
4 0 0 DROP icmp -- * * 10.0.0.0/24 0.0.0.0/0 一条规则下发后分别存在进出两条规则在router中,即neutron-l3-agent-iv4a7700495 ,neutron-l3-agent-ov4a7700495 ,用于进数据网络的包的默认处理和出数据网络的包的默认处理。 neutron-l3-agent-fwaas-defau用于默认丢弃没有被以上规则处理的所有包。

所以默认neutron是丢弃所有的数据包

lbaas分析

haproxy

haproxy 配置中分成五部分内容,分别如下: global:参数是进程级的,通常是和操作系统相关。这些参数一般只设置一次,如果配置无误,就不需要再次进行修改。 defaults:配置默认参数,这些参数可以被用到frontend,backend,Listen组件。 frontend:接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend。 backend:后端服务集群的配置,是真实服务器,一个Backend对应一个或者多个实体服务器。 Listen Fronted和backend的组合体。

LBaasv2 可以看做 OpenStack Neutron 对各种物理负载均衡器的虚拟化。它的概念可以和 HAProxy 中的概念进行类比:

HAProxy 的概念 LBaasv2 的概念 说明
Driver LBaas v2也是采取 driver 模型来支持多种物理的负载均衡器。LBaasv2 默认实现了 HAProxy driver,同时,它也支持多个其他 Vendor driver。厂商驱动
Frontend Listener LBaasv2采用Listener方式将流量转移到不同的pool中的member。
Backend Pool 代表Listener所监听的负载后端的虚拟机池。
Backend server Member Member 对应的是 pool 里面处理网络请求的一个 OpenStack Nova 虚机
Health check Health monitor 它用来监测 pool 里面 member 的状态,支持 HTTP, TCP, 和 ping 等多种检测方法。在 Nuetron 中这是可选的,如果没有 Health monitor,pool 会一直认为所有的 member 都是 ACTIVE 状态,这样所有的 member 会一直出现在 VIP 的分发列表中,哪怕 member 对应的实例不能响应网络请求。这在实际应用中会造成负载均衡的响应异常。

neutron-lbaas

网络节点上,neutron-lbaas-agent

(1)为每个带有 active VIP 的 pool 创建了一个 network namespace,它以 qlbaas- 命名

(2)该 interface 挂载 OVS br-int 上并被打上了它所在的 network(pool -> subnet -> network) 对应的本地 VLAN ID:

(3) ps -elf | grep -v agent | grep haproxy

(4) 根据步骤4查看haproxy.conf 如 /var/lib/neutron/lbaas/v2/5735af3c-11bc-49b6-a3e1-dc1c1b4ebd37

floating IP原理

当 router 接收到 instance 的数据包,并将其转发到外网时: router 会修改包的源地址为自己的外网地址,这样确保数据包转发到外网,并能够从外网返回。 router 修改返回的数据包,并转发给真正的 instance。 这个行为被称作 Source NAT。

floating IP 提供静态 NAT 功能,建立外网 IP 与 instance 租户网络 IP 的一对一映射。

floating IP 是配置在 router 提供网关的外网 interface 上的,而非 instance 中。

router 会根据通信的方向修改数据包的源或者目的地址。

进入路由的namespace iptables -t nat -S 查看nat表

DHCP

neutron dhcp为租户网络提供DHCP服务,即IP地址动态分配,另外还会提供metadata请求服务。

3个主要的部件:

DHCP agent scheduler:负责DHCP agent与network的调度。

DHCP agent:为租户网络提供DHCP的功能,提供metadata request服务。

DHCP driver:即dnsmasq,用于管理DHCP server。

Dnsmasq 是被 Neutron 用来提供 DHCP 和 DNS 服务的一个开源程序,即DHCP driver部分。它提供 DNS 缓存和 DHCP 服务功能。作为域名解析服务器(DNS),dnsmasq可以通过缓存 DNS 请求来提高对访问过的网址的连接速度。作为DHCP 服务器,dnsmasq 可以为局域网电脑提供内网ip地址和路由。DNS和DHCP两个功能可以同时或分别单独实现。dnsmasq轻量且易配置,适用于主机较少的网络。

根据整个dhcp处理的流程,dhcp模块主要由Neutron api、core plugin(如linux bridge plugin,ovs plugin等)、dhcp agent scheduler、dhcp agent、dhcp driver(dnsmasq)构成。

对应架构图中数字,有以下几个接口: 1.network/subnet/port的操作 2.agent management/agent scheduler的操作 3.network/subnet/port操作会发送rpc请求到dhcp agent。 4.agentscheduler db发送rpc请求到dhcp agent。 5.dhcp agent通过DhcpPluginApi发送rpc请求到core plugin,操作相应的数据库。 6.dhcp agent调用dhcp driver进行dhcp相关操作。

虚机获取固定IP (Fixed IP)主要分为两个步骤:

在创建虚机过程中,Neutron 随机生成 MAC 和 从配置数据中分配一个固定IP 地址,并保存到 Dnsmasq 的 hosts 文件中,让 Dnsmasq 做好准备。

虚机在启动时向 Dnsmasq 获取 IP 地址

红色为创建虚拟机的数据流

绿色为虚拟机启动的数据流

创建虚机时的数据流

Controller 节点上的 Neutron Server 接到该请求后,会开始下面的过程

步骤 2 ~ 6:Neutron Server 生成 MAC 和 IP。 其中 MAC 是由任意数组成的;Fixed IP 是从保存在数据库中的管理员配置的网络和地址数据生成的。

步骤 7 ~ 10: 调用 L3 Agent 和 OVS 执行一些操作。

步骤 12 ~ 14:通过 AMQP 的 cast 消息给 Neutron 节点上的 DHCP Agent,告诉它 Port 创建结束以及 新分配的 Port 的数据。

步骤 13:返回Port 给 nova-compute。

步骤 15:Neturon 节点上的 DHCP Agent 根据接收到的 Port 创建完成通知,重新生成 Dnsmasq 的 hosts 文件,然后让 Dnsmasq 重新加载该文件。Nova 拿到 Port 的数据后,会写入虚机的 libvirt.xml 文件。

安全组

其中id的前10位数字被用作虚机对外连接的qbr(同时也是tap口)的id。i或o加上前9位数字被用作安全组chain的id。所有的规则默认都在Compute节点上的filter表(默认表)中实现,分别来查看filter表的INPUT、OUTPUT、FORWARD三条链上的规则。

跟安全组相关的规则被重定向到neutron-openvswi-INPUT。 查看其规则,只有一条

某个vm的安全组相关规则的chain的名字,跟vm的id的前9个字符有关。

因此,要快速查找qbr-XXX上相关的iptables规则,可以用iptables -S列出(默认是filter表)所有链上的规则,其中含有id的链即为虚拟机相关的安全组规则。其中–physdev-in表示即将进入某个网桥的端口,–physdev-out表示即将从某个网桥端口发出。

iptables -S | grep tap4ca9818f-53

3.1 配置

节点 配置文件 配置项 说明

controller /etc/nova/nova.conf security_group_api = neutron 使得 nova secgroup* 命令使用的是 neutron 安全组的 API

/etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = True

firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 启用 Neutron 安全组并指定驱动

nova-compute /etc/nova/nova.conf firewall_driver = nova.virt.firewall.NoopFirewallDriver 禁用 nova 安全组

/etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = True

enable_ipset = True

firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 启用 Neutron 安全组并指定驱动

network /etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = True

enable_ipset = True

firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 启用 Neutron 安全组并指定驱动

neutron 也提供两种安全组的实现:IptablesFirewallDriver 和 OVSHybridIptablesFirewallDriver

neutron.agent.linux.iptables_firewall.IptablesFirewallDriver : iptables-based FirewallDriver implementation

neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver: subclass of IptablesFirewallDriver with additional bridge

默认值是 neutron.agent.firewall.NoopFirewallDriver,表示不使用 neutron security group。

参考:http://www.cnblogs.com/wanstack/tag/Neutron/

https://www.cnblogs.com/sammyliu/p/4658746.html

neutron相关知识的更多相关文章

  1. 【Python五篇慢慢弹(5)】类的继承案例解析,python相关知识延伸

    类的继承案例解析,python相关知识延伸 作者:白宁超 2016年10月10日22:36:57 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给 ...

  2. 移动WEB像素相关知识

    了解移动web像素的知识,主要是为了切图时心中有数.本文主要围绕一个问题:怎样根据设备厂商提供的屏幕尺寸和物理像素得到我们切图需要的逻辑像素?围绕这个问题以iphone5为例讲解涉及到的web像素相关 ...

  3. listener监听器的相关知识

    从别人的博客上我学习了listener的相关知识现在分享给大家 1.概念: 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上 ...

  4. UIViewController相关知识

    title: UIViewController 相关知识date: 2015-12-13 11:50categories: IOS tags: UIViewController 小小程序猿我的博客:h ...

  5. 【转】java NIO 相关知识

    原文地址:http://www.iteye.com/magazines/132-Java-NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的 ...

  6. NSString使用stringWithFormat拼接的相关知识

    NSString使用stringWithFormat拼接的相关知识 保留2位小数点 1 2 3 4 //.2代表小数点后面保留2位(2代表保留的数量) NSString *string = [NSSt ...

  7. iOS网络相关知识总结

    iOS网络相关知识总结 1.关于请求NSURLRequest? 我们经常讲的GET/POST/PUT等请求是指我们要向服务器发出的NSMutableURLRequest的类型; 我们可以设置Reque ...

  8. 电路相关知识--读<<继电器是如何成为CPU的>>

    电路相关知识–读<<继电器是如何成为CPU的>> */--> *///--> *///--> 电路相关知识–读<<继电器是如何成为CPU的> ...

  9. 地址标记,SpringMVC转发与调用相关知识存档

    1.mytest_mavenprj1中,index的 <a href="login/login.html">点击登录</a> 与 <a href=&q ...

随机推荐

  1. [2017BUAA软工助教]个人项目准备工作

    BUAA软工个人项目准备工作 零.注册Github个人账号(你不会没有吧..) 这是Git的使用教程: http://www.cnblogs.com/schaepher/p/5561193.html ...

  2. 多线程系列之二:Single Thread Execution 模式

    一,什么是SingleThreadExecution模式?同一时间内只能让一个线程执行处理 二,例子 1.不安全的情况 用程序模拟 三个人频繁地通过一个只允许一个人经过的门.当人通过时,统计人数便会增 ...

  3. c#+linux+mono+Redis集群(解决无法连接Redis的问题)

    在linux环境中使用mono来执行c#的程序, 在连接redis的时候遇到了无法连接数据库的错误.如下: Unhandled Exception:StackExchange.Redis.RedisC ...

  4. winform使用相关

    1.回车键触发按钮点击事件——回车登录 设置窗体的AccessButton属性 2.密码框样式设置 设置PasswordChar为想要的密码显示的样式,如*  3.设置窗口居中 设置StartPosi ...

  5. 【翻译】asp.net core2.1认证和授权解密

    asp.net core2.1认证和授权解密 本篇文章翻译自:https://digitalmccullough.com/posts/aspnetcore-auth-system-demystifie ...

  6. MyBatis全局配置文件的各项标签3

    mapper 将sql映射注册到全局配置中,这个我们在上一章已经使用过了, resource 这个属性是用来引用类路径下的sql映射文件 url 这个属性是用来引用网络路径或磁盘路径下的sql映射文件 ...

  7. 机顶盒webview开发调试

    安装node的anywhere插件  启动本地服务器后 使用chrome的DevTool----->   chrome://inspect/#devices 点击inspect  第一次需要FQ ...

  8. 区分Python中的id()和is以及Python中字符串的intern机制

    参考:1. https://blog.csdn.net/lnotime/article/details/81194633 2.https://segmentfault.com/q/1010000015 ...

  9. linux命令logger使用

    先从别的地方抄过来全部的解释,如下: **options (选项):** -d, --udp 使用数据报(UDP)而不是使用默认的流连接(TCP) -i, --id 逐行记录每一次logger的进程I ...

  10. 如何在集合中巧用Where来查找相关元素

    在我们的项目中我们经常会查找一些集合中的重要元素,当然我们可以使用常规的foreach循环和if语句来查询,但是我们要学会使用System.Linq命名空间下面的静态类Enumerable下面的静态方 ...