【星海随笔】SDN neutron (二) Neutron-plugin(ML2)

Neutron架构之Neutron-plugin Core-plugin(ML2)篇
Neutron-server接收两种请求:
REST API请求:接收REST API请求,并将REST API分发到对应的Plugin(L3RouterPlugin)。
RPC请求:接收Plugin agent请求,分发到对应的Plugin(NeutronL3agent)。
Neutron-plugin分为Core-plugin和Service-plugin。
Core-plugin:ML2负责管理二层网络,ML2主要包括Network、Subnet、Port三类核心资源,对三类资源进行操作的REST API是原生支持的。
Service-plugin:实现L3-L7网络,包括Router、Firewall、VPN。

core-plugin
core-plugin(ML-2)
|- - - - - - - - - - - - - - - - - - - - - - - |
Type Manager(Vxlan) - - - - - - - Mechanism Manager(openvswitch )
每部分又分为Manager和Driver

执行流
_eventlet_wsgi_server():
service.serve_wsgi(service.NeutronApiService)
WsgiService.start
config.load_paste_app(app_name)
neutron.api.v2.router:APIRouter.factory
Neutron插件是Neutron的一个重要组成部分,它允许Neutron与不同的网络技术进行集成。
首先,我们需要安装Neutron插件。Neutron插件可以是Open vSwitch、Linux Bridge、Cisco Nexus、VMware NSX等。在安装Neutron插件之前,我们需要确保已经安装了Neutron服务。
以Open vSwitch为例,我们可以使用以下命令安装Open vSwitch插件:
sudo apt-get install neutron-plugin-openvswitch-agent
安装Neutron插件后,我们需要配置它。配置文件通常位于/etc/neutron/plugins/目录下。以Open vSwitch为例,我们需要编辑/etc/neutron/plugins/ml2/ml2_conf.ini文件。
在该文件中,我们需要配置以下参数:
- type_drivers:指定支持的网络类型,例如vlan、vxlan等。
- tenant_network_types:指定租户网络类型,例如vlan、vxlan等。
- mechanism_drivers:指定网络机制驱动程序,例如Open vSwitch、Linux Bridge等。
- bridge_mappings:指定物理网络和虚拟网络之间的映射关系。
以下是一个示例配置文件:
[ml2]
type_drivers = flat,vlan,vxlan
tenant_network_types = vxlan
mechanism_drivers = openvswitch [ml2_type_flat]
flat_networks = external [ml2_type_vxlan]
vni_ranges = 1:1000 [securitygroup]
enable_security_group = True
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver [ovs]
bridge_mappings = external:br-ex
在上面的示例中,我们指定了Open vSwitch插件支持的网络类型为flat、vlan和vxlan。我们还指定了租户网络类型为vxlan,并将机制驱动程序设置为Open vSwitch。我们还指定了物理网络和虚拟网络之间的映射关系,例如将外部网络映射到br-ex网桥。
完成Neutron插件的配置后,我们需要重启Neutron服务以使配置生效。我们可以使用以下命令重启Neutron服务:
sudo service neutron-server restart
sudo service neutron-plugin-openvswitch-agent restart
neutron-plugin 分为 core-plugin 和 service-plugin 两类
L2-L3称为core plugin,包含network、subnet、port
L4-L7称为service plugin,包含router、firewall、loadbalancer、VPN、metering等等
Openstack neutron加载plugin
RESOURCES = {'network': 'networks','subnet': 'subnets','subnetpool': 'subnetpools','port': 'ports'}
SUB_RESOURCES = {}
COLLECTION_ACTIONS = ['index', 'create']
MEMBER_ACTIONS = ['show', 'update', 'delete']
REQUIREMENTS = {'id': attributes.UUID_PATTERN, 'format': 'json'}
class APIRouter(wsgi.Router):@classmethoddef factory(cls, global_config, **local_config):return cls(**local_config)def __init__(self, **local_config):#创建mappermapper = routes_mapper.Mapper()#获取NeutornManage的core_plugin,这个定义在/etc/neutron/neutron.conf,比如我的是core_plugin = ml2plugin = manager.NeutronManager.get_plugin()#扫描neutron/extensions下所有的extensionext_mgr = extensions.PluginAwareExtensionManager.get_instance()ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)col_kwargs = dict(collection_actions=COLLECTION_ACTIONS,member_actions=MEMBER_ACTIONS)#构建映射规则函数def _map_resource(collection, resource, params, parent=None):allow_bulk = cfg.CONF.allow_bulkallow_pagination = cfg.CONF.allow_paginationallow_sorting = cfg.CONF.allow_sorting#创建controllercontroller = base.create_resource(collection, resource, plugin, params, allow_bulk=allow_bulk,parent=parent, allow_pagination=allow_pagination,allow_sorting=allow_sorting)path_prefix = Noneif parent:path_prefix = "/%s/{%s_id}/%s" % (parent['collection_name'],parent['member_name'],collection)mapper_kwargs = dict(controller=controller,requirements=REQUIREMENTS,path_prefix=path_prefix,**col_kwargs)# mapper.collection这个就是构建映射规则#collection:一个字符串,就是资源的复数形式,比如networks#resource:一个字符串,就是资源的单数形式,比如networkreturn mapper.collection(collection, resource,**mapper_kwargs)#构建/的映射规则mapper.connect('index', '/', controller=Index(RESOURCES))for resource in RESOURCES:#针对每一个核心资源(network、subnet等),调用_map_resource,构建映射规则_map_resource(RESOURCES[resource], resource,attributes.RESOURCE_ATTRIBUTE_MAP.get(RESOURCES[resource], dict()))resource_registry.register_resource_by_name(resource)#SUB_RESOURCES是空的,没啥用for resource in SUB_RESOURCES:_map_resource(SUB_RESOURCES[resource]['collection_name'], resource,attributes.RESOURCE_ATTRIBUTE_MAP.get(SUB_RESOURCES[resource]['collection_name'],dict()),SUB_RESOURCES[resource]['parent'])#清除当前配置在策略引擎中的所有规则。其在单元测试中和核心API router初始化的最后调用,确保在所有扩展加载之后加载规则policy.reset()#初始化wsgi.Routersuper(APIRouter, self).__init__(mapper)
四种组网模型

Type Manager
#neutron/plugins/ml2/managers.py
class TypeManager(stevedore.named.NamedExtensionManager):"""Manage network segment types using drivers."""def __init__(self):# Mapping from type name to DriverManagerself.drivers = {}LOG.info(_("Configured type driver names: %s"),cfg.CONF.ml2.type_drivers)super(TypeManager, self).__init__('neutron.ml2.type_drivers',cfg.CONF.ml2.type_drivers,invoke_on_load=True)LOG.info(_("Loaded type driver names: %s"), self.names())self._register_types()self._check_tenant_network_types(cfg.CONF.ml2.tenant_network_types)def create_network_segments(self, context, network, tenant_id):"""Call type drivers to create network segments."""segments = self._process_provider_create(network)session = context.sessionwith session.begin(subtransactions=True):network_id = network['id']if segments:for segment in segments:segment = self.reserve_provider_segment(session, segment)db.add_network_segment(session, network_id, segment)else:segment = self.allocate_tenant_segment(session)db.add_network_segment(session, network_id, segment)
Type Drivers
- Flat模型最为简单,所有的虚拟机共用一个私有IP网段,IP地址在虚拟机启动时完成注入,虚拟机间的通信直接通过HyperVisor中的网桥转发,公网流量在该网段的网关上进行NAT(Nova-network实现为开启nova-network主机内核的iptables,Neutron实现为网络节点上的l3-agent)。Flat DHCP模型与Flat区别在于网桥中开启了DHCP进程,虚拟机通过DHCP消息获得IP地址(Nova-network实现为nova-network主机中的dnsmaq,Neutron实现为网络节点上的dhcp-agent)。
Dnsmasq 的工作原理
Dnsmasq 在接受到用户的一个 DNS 请求时,首先会查找 /etc/hosts 这个文件,如果 /etc/hosts 文件没有请求的记录,然后查找 /etc/resolv.conf 中定义的外部 DNS(也叫上游 DNS 服务器,nameserver 配置),外部 DNS 通过递归查询查找到请求后响应给客户端,然后 dnsmasq 将请求结果缓存下来(缓存到内存)供后续的解析请求。
配置 Dnsmasq 为 DNS 缓存服务器,同时在 /etc/hosts 文件中加入本地内网解析,这样一来每当内网机器查询时就会优先查询 hosts 文件,这就等于将 /etc/hosts 共享给全内网机器使用,从而解决内网机器互相识别的问题。相比逐台机器编辑 hosts 文件或者添加 Bind DNS 记录,仅编辑一个 hosts 文件,这简直太容易了。
- VLAN模型引入了多租户机制,虚拟机可以使用不同的私有IP网段,一个租户可以拥有多个IP网段。虚拟机IP通过DHCP消息获取IP地址(Nova-network实现为nova-network主机中的dnsmaq,Neutron实现为网络节点上的dhcp-agent)。网段内部虚拟机间的通信直接通过HyperVisor中的网桥转发,同一租户跨网段通信通过网关路由,不同租户通过网关上的ACL进行隔离,公网流量在该网段的网关上进行NAT(Nova-network实现为开启nova-network主机内核的iptables,Neutron实现为网络节点上的l3-agent)。如果不同租户逻辑上共用一个网关,则无法实现租户间IP地址的复用。
- Overlay模型(主要包括GRE和VxlAN隧道技术),相比于VLAN模型有以下改进。1)租户数量从4K增加到16million;2)租户内部通信可以跨越任意IP网络,支持虚拟机任意迁移;3)一般来说每个租户逻辑上都有一个网关实例,IP地址可以在租户间进行复用;4)能够结合SDN技术对流量进行优化。

TYPE=0x8100,PRI是优先级字段,CFI不怎么常用,以太网中CFI=0。后面12位的VID就是VLAN的标签位,也就是说802.1q中一个局域网中最多有4096个VLAN,不过不同的交换机对VLAN的规划是不同的,用户实际在一台交换机上能用的VLAN数目要比4096少很多。很简单的一个字段吧,没有什么分域,更不能用来寻址,就只是一个标签,不过这对于传统局域网里的网络虚拟化来说就足够了。

vxlan与vlan区别:
vxlan支持更多的二层网络
vxlan使用12位bit表示vlan ID,因此最多支持2^12=4094个vlan
vxlan使用的ID使用24位bit,最多可以支持2^24个
已有的网络路径利用效率更高
vlan使用spanning tree protocol避免环路,会将一半的网络路径阻塞
vxlan的数据包封装成UDP通过网络层传输,可以使用所有的网络路径
防止物理交换机Mac表耗尽
vlan需要在交换机的Mac表中记录Mac物理地址
vxlan采用隧道机制,Mac物理地址不需记录在交换机
依赖物理的二层来建立虚拟的大二层(vlan模式)
物理的二层指的是:物理网络是二层网络,基于以太网协议的广播方式进行通信
虚拟的二层指的是:neutron实现的虚拟的网络也是二层网络(openstack的vm机所用的网络必须是大二层),也是基于以太网协议的广播方式进行通信,但毫无疑问的是该虚拟网络依赖于物理的二层网络
依赖物理的三层来建立虚拟的大二层(gre模块与vxlan模式)
物理的三层指的是:物理网络是三层网络,基于ip路由的方式进行通信
虚拟的二层指的是:neutron实现的虚拟的网络仍然是二层网络(openstack的vm机所用的网络必须是大二层),仍然是基于以太网协议的广播方式进行通信,但毫无疑问的是该虚拟网络依赖于物理的三层网络,这有点类似于VPN的概念,根本原理就是将私网的包封装起来,最终打上隧道的ip地址传输。
用户(例如demo用户)可以在自己的project下创建网络(L2 network),该网络就是在大二层的基础上划分出来的,是一个隔离的二层网段。类似于物理网络世界中的虚拟 LAN (VLAN),每建立一个l2 network,都会被分配一个段ID,该段ID标识一个广播域,这个ID是被随机分配的,除非使用管理员身份在管理员菜单下,才可以手动指定该ID
子网是一组 IPv4 或 IPv6 地址以及与其有关联的配置。它是一个地址池,OpenStack 可从中向虚拟机 (VM) 分配 IP 地址。每个子网指定为一个无类别域间路由 (Classless Inter-Domain Routing) 范围,必须与一个网络相关联。除了子网之外,租户还可以指定一个网关、一个域名系统 (DNS) 名称服务器列表,以及一组主机路由。这个子网上的 VM 实例随后会自动继承该配置。
每个网络使用自己的 DHCP Agent,每个 DHCP Agent 在一个 Network namespace 内
不同网络内的IP地址可以重复(overlapping)
跨网络的子网之间的流量必须走 L3 Virtual Router
L2 network之Provider与Tenant的区别
Provider network 是由 Admin 用户创建的,而 Tenant network 是由 tenant 普通用户创建的。
Provider network 和物理网络的某段直接映射,比如对应某个 VLAN,因此需要预先在物理网络中做相应的配置。而 tenant network 是虚拟化的网络,Neutron 需要负责其路由等三层功能。
对 Flat 和 VLAN 类型的网络来说,只有 Provider network 才有意义。即使是这种类型的 tenant network,其本质上也是对应于一个实际的物理段。
对 GRE 和 VXLAN 类型的网络来说,只有 tenant network 才有意义,因为它本身不依赖于具体的物理网络,只是需要物理网络提供 IP 和 组播即可。
Provider network 根据 admin 用户输入的物理网络参数创建;而 tenant work 由 tenant 普通用户创建,Neutron 根据其网络配置来选择具体的配置,包括网络类型,物理网络和 segmentation_id。
创建 Provider network 时允许使用不在配置项范围内的 segmentation_id。
Mechanism Manager
ML2 plugin 通过 neutron.plugins.ml2.managers.MechanismManager 与配置了的 mechanism driver 交互。
MechanismManager管理MechanismDriver。
MechanismDriver在创建、更新、删除网络或端口的时候被调用,负责二层网络技术底层的具体实现,和不同的网
络设备进行交互。在每次事件中会调用到MechanismDriver的两个方法
Mechanism Driver
这部分是对各种 L2 技术的支持,例如 Open vSwitch,linux bridge 等等。
会按照配置顺序依次调用每一个Driver的对应函数来完成,比如对需要配置交换机的操作,可能Open vSwitch虚拟交换机和外部真实的物理交换机比如Cisco交换机都需要进行配置,这个时候需要Open vSwitch Mechanism Driver和Cisco Mechanisam Driver都被调用处理。
extension drivers,type drivers 和 mechanism drivers,如果其中任何一个不能接受新创建的 Network,都会导致创建 Network 失败,并且清除在 Network 在 DB 中的记录。
整个流程与创建 Network 类似。差别是少了调用 type drivers,因为 type drivers 针对的是 Network type 的支持,所以没有必要在 Port create 中调用。另一方面,创建 Port 会调用 rpc 通知 L2 agents,这是因为 Port 在 ML2 中还只是一个内存或者 DB 中的对象,真正在 SDN 中起作用的,是在各个 L2 agents 上的虚拟端口。ML2 通过 rpc 通知到 L2 agents,并创建相应的虚拟端口,这样,虚机,虚拟路由器,DHCP 服务等都能基于虚机端口提供网络服务。
Neutron 默认采用的 开源Open vSwitch 创建的虚机交换机
Mechanism Manager分发操作并具体传递操作到Mechanism Driver的方式与Type Manager相同,但是一个需要Mechanism Driver处理的操作是:会按照配置顺序依次调用每一个Driver的对应函数来完成,比如对需要配置交换机的操作,可能Open vSwitch虚拟交换机和外部真实的物理交换机比如Cisco交换机都需要进行配置,这个时候需要Open vSwitch Mechanism Driver和Cisco Mechanisam Driver都被调用处理。
yum install openstack-neutron-openvswitch -y
vi /etc/neutron/plugins/ml2/openvswitch_agent.ini
[ovs]
tunnel_bridge = br-tun
local_ip = 192.168.100.20 #隧道IP地址 管理网卡IP地址
integration_bridge = br-int
tenant_network_type = vxlan
tunnel_type = vxlan
tunnel_id_ranges = 1:1000
enable_tunneling = true
[agent]
tunnel_types = vxlan
l2_population = true
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = true
systemctl start neutron-openvswitch-agent.service
systemctl enable neutron-openvswitch-agent.service
ifconfig
brctl show
ovs-vsctl show
Neutron-VLAN-OVS

与Linux bridge不同,openvswitch 不是通过eth1.1 eth1.2这样的vlan接口来隔离不同的vlan,而是通过openvswitch的流表规则来指定如何对进出br-int的数据进行转发,实现不同vlan的隔离。
图中计算节点的所有虚拟机都连接在int网桥上,虚拟机分为两个网络。Int网桥会对到来的数据包根据network的不同打上vlan id号,然后转发到eth网桥,eth网桥直连物理网络。这时候流量就从计算节点到了网络节点。
网络节点的ehx int网桥的功能相似,多了一个ex网桥,这个网桥是管理提前创建好的,和物理网卡相连,ex网桥和int网桥之间通过一对patch-port相连,虚拟机的流量到达int网桥后经过路由到ex网桥。
OpenvSwitch的组成
1.ovs的主要组成模块如下:
ovs-vswitchd:OVS守护进程是,OVS的核心部件,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换(flow-based switching)。它和上层 controller 通信遵从 OPENFLOW 协议,它与 ovsdb-server 通信使用 OVSDB 协议,它和内核模块通过netlink通信,它支持多个独立的 datapath(网桥),它通过更改flow table 实现了绑定和VLAN等功能。
ovsdb-server:轻量级的数据库服务,主要保存了整个OVS 的配置信息,包括接口啊,交换内容,VLAN啊等等。ovs-vswitchd 会根据数据库中的配置信息工作。它于 manager 和 ovs-vswitchd 交换信息使用了OVSDB(JSON-RPC)的方式。
ovs-dpctl:一个工具,用来配置交换机内核模块,可以控制转发规则。
ovs-vsctl:主要是获取或者更改ovs-vswitchd 的配置信息,此工具操作的时候会更新ovsdb-server 中的数据库。
ovs-appctl:主要是向OVS 守护进程发送命令的,一般用不上。
ovsdbmonitor:GUI 工具来显示ovsdb-server 中数据信息。
ovs-controller:一个简单的OpenFlow 控制器
ovs-ofctl:用来控制OVS 作为OpenFlow 交换机工作时候的流表内容。
2.OpenvSwitch的工作流程
通过ovs实现虚拟机和外部通信的过程,通信流程如下:
1.VM实例 instance 产生一个数据包并发送至实例内的虚拟网络接口 VNIC,图中就是 instance 中的 eth0.
2.这个数据包会传送到物理机上的VNIC接口,如图就是vnet接口.
3.数据包从 vnet NIC 出来,到达桥(虚拟交换机) br100 上.
4.数据包经过交换机的处理,从物理节点上的物理接口发出,如图中物理机上的 eth0 .
5.数据包从 eth0 出去的时候,是按照物理节点上的路由以及默认网关操作的,这个时候该数 据包其实已经不受你的控制了.
注:一般 L2 switch 连接 eth0 的这个口是一个 trunk 口, 因为虚拟机对应的 VNET 往往会设置 VLAN TAG, 可以通过对虚拟机对应的 vnet 打 VALN TAG 来控制虚拟机的网络广播域. 如果跑多个虚拟机的话, 多个虚拟机对应的 vnet 可以设置不同的 vlan tag, 那么这些虚拟机的数据包从 eth0(4)出去的时候, 会带上TAG标记. 这样也就必须是 trunk 口才行。
# 添加网桥:
ovs-vsctl add-br br0 # 列出所有网桥:
ovs-vsctl list-br# 判断网桥是否存在:
ovs-vsctl br-exists br0# 将物理网卡挂载到网桥上:
ovs-vsctl add-port br0 eth0# 列出网桥中的所有端口:
ovs-vsctl list-ports br0# 列出所有挂载到网卡的网桥:
ovs-vsctl port-to-br eth0# 查看ovs的网络状态:
ovs-vsctl show# 删除网桥上已经挂载的网口:
ovs-vsctl del-port br0 eth0# 删除网桥:
ovs-vsctl del-br br0# 设置控制器:
ovs-vsctl set-controller br0 tcp:ip:6633# 删除控制器:
ovs-vsctl del-controller br0# 设置支持OpenFlow Version 1.3:
ovs-vsctl set bridge br0 protocols=OpenFlow13 # 删除OpenFlow支持设置:
ovs-vsctl clear bridge br0 protocols # 设置vlan标签:
ovs-vsctl add-port br0 vlan3 tag=3 -- set interface vlan3 type=internal# 删除vlan标签:
ovs-vsctl del-port br0 vlan3 # 查询 VLAN:
ovs-vsctl show
ifconfig vlan3 # 查看网桥上所有交换机端口的状态:
ovs-ofctl dump-ports br0# 查看网桥上所有的流规则:
ovs-ofctl dump-flows br0# 查看ovs的版本:
ovs-ofctl -V# 给端口配置tagovs-vsctl set port br-ex tag=101
OpenFlow协议定义了交换机在报文匹配失败时向控制器申请流表的方法,当交换机收到一个不能被当前流表各条流匹配的数据包时,通过将失配报文的相关信息封装在Packet-In消息中发送给控制器,让控制器知晓报文失配情况,由控制器通过Flow-Mod等消息向交换机安装新流表。
extension
在neutron/plugins/ml2/manager.py文件中,除了Type Manager与Mechanism之外还定义有Extension Manger
extension应该放在neutron/extensions文件夹下,或者在配置文件中设置api_extensions_path
extension的class名应该和文件同名,当然首字母应该大写
应该实现neutron.api.extensions.py中ExtensionDescriptor定义的接口
在对应的plugin的supported_extension_aliases 中增加我们extension的别名。
create_network
create_network_in_db
extension_manager.process_create_network
type_manager.create_network_segments
mechanism_manager.create_network_precommit
db commit
mechanism_manager.create_network_postcommit
create_subnet
create_subnet_in_db
extension_manager.process_create_subnet
mechanism_manager.create_subnet_precommit
db commit
mechanism_manager.create_subnet_postcommit
create_port
create_port_in_db
extension_manager.process_create_port
port biding
mechanism_manager.create_port_precommit
db commit
mechanism_manager.create_port_postcommit
相关文章:
【星海随笔】SDN neutron (二) Neutron-plugin(ML2)
Neutron架构之Neutron-plugin Core-plugin(ML2)篇 Neutron-server接收两种请求: REST API请求:接收REST API请求,并将REST API分发到对应的Plugin(L3RouterPlugin)。 RPC请求:接收Plugin agent请求&#…...
野火i.MX6ULL开发板检测按键evtest(Linux应用开发)
之前一直查找不到evtest,因为没有下载成功,很可能是网络不好,下次可以软件源可以换成国内大学镜像网站。 重新断开板子电源启动,再次连接网络,下载evtest成功!!...
k8s存储
nfs 理论上nfs 其实并不是存储设备,它是一种远程共享存储服务。 k8s 存储卷 volume emptyDir:可以实现pod中的容器之间共享数据, 但是存储卷不能持久化数据,且会随着pod的生命周期一起删除。 hostpash:可以实现持久…...
数据分析实战 | 贝叶斯分类算法——病例自动诊断分析
目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 八、模型评价 九、模型调参 十、模型预测 一、数据及分析对象 CSV文件——“bc_data.csv” 数据集链接:https://download.csdn.net/d…...
实用技巧:嵌入式人员使用http服务模拟工具模拟http服务器测试客户端get和post请求
文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134305752 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…...
P9836 种树
容易想到分解因数。 对于一个数 p p p 的因数个数,假设它可以被分解质因数成 a 1 i 1 a 2 i 2 a 3 i 3 ⋯ a k c k a_1^{i_1} a_2^{i_2} a_3^{i_3}\cdots a_k^{c_k} a1i1a2i2a3i3⋯akck 的形式,则其因数个数为 ( i 1 1 ) ( i 2 1 )…...
C# 查询腾讯云直播流是否存在的API实现
应用场景 在云考试中,为防止作弊行为的发生,会在考生端部署音视频监控系统,当然还有考官方监控墙系统。在实际应用中,考生一方至少包括两路直播流: (1)前置摄像头:答题的设备要求使…...
JAVA开源项目 于道前端项目 启动步骤参考
1. 安装 启动过程有9个步骤: 1.1 安装 Node JS , V18版本的 (安装步骤省略) 1.2 安装 npm install -g yarn ,node JS里边好像自带npm ,通过npm的命令安装 yarn 1.3 切换到项目中去安装,npm install &a…...
深入理解ElasticSearch分片
1. 路由计算 当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?首先这肯定不会是随机的&…...
【Python】AppUI自动化—appium自动化元素定位、元素事件操作(17)下
文章目录 前言一.Appium 元素定位1.定位方式种类2.如何定位2.1 id定位2.2 className定位2.3 content-desc 定位2.4 Android Uiautomator定位4.1 text定位4.2 text模糊定位4.3 text正则匹配定位4.4 resourceId定位4.5 resourceId正则匹配定位4.6 className定位4.7 className正则…...
SpringBoot使用MyBatis多数据源
SpringBoot使用MyBatis多数据源 我们以 Mybatis Xml和注解两种版本为例,给大家展示如何如何配置多数据源。 1、注解方式 数据库文件: DROP TABLE IF EXISTS users; CREATE TABLE users (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键id,userN…...
小程序版本审核未通过,需在开发者后台「版本管理—提交审核——小程序订单中心path」设置订单中心页path,请设置后再提交代码审核
小程序版本审核未通过,需在开发者后台「版本管理—提交审核——小程序订单中心path」设置订单中心页path,请设置后再提交代码审核 因小程序尚未发布,订单中心不能正常打开查看,请先发布小程序后再提交订单中心PATH申请 初次提交…...
Netty入门指南之NIO Selector监管
作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者! 个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏:Netty应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言问题解…...
Spring Cloud学习(六)【统一网关 Gateway】
文章目录 网关的功能搭建网关服务路由断言工厂Route Predicate Factory路由过滤器 GatewayFilter过滤器执行顺序跨域问题处理 网关的功能 网关功能: 身份认证和权限校验服务路由、负载均衡请求限流 在SpringCloud中网关的实现包括两种: gatewayzuul …...
基于单片机的空调智能控制器的设计
**单片机设计介绍,基于单片机的空调智能控制器的设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的空调智能控制器需要具备输入输出端口、定时器、计数器等模块,以便对空调进行精确控制。下…...
Spring Boot自动配置原理、实战、手撕自动装配源码
Spring Boot自动配置原理 相比较于传统的 Spring 应用,搭建一个 SpringBoot 应用,我们只需要引入一个注解 SpringBootApplication,就可以成功运行。 前面四个不用说,是定义一个注解所必须的,关键就在于后面三个注解&a…...
111111111111111
全局锁 就是对整个数据库进行加锁,加锁之后整个数据库就处于只读状态,后续的DML写语句,DDL语句,以及对更新事务的提交操作都会被阻塞,典型地使用场景就是做整个数据库的逻辑备份,对所有的表进行锁定&#x…...
React动态生成二维码和毫米(mm)单位转像素(px)单位
一、使用qrcode.react生成二维码,qrcode.react - npm 很简单,安装依赖包,然后引用就行了 npm install qrcode.react或者 yarn add qrcode.react直接上写好的代码 import React, {useEffect, useState} from react; import QRCode from qr…...
SpringMvc 常见面试题
1、SpringMvc概述 1.1、什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦&am…...
jmeter接口自动化测试工具在企业开展实际的操作
在企业使用jmeter开展实际的接口自动化测试工具,建议按如下操作流程, 可以使整个接口测试过程更规范,更有效。 接口自动化的流程: 1、获取到接口文档:swagger、word、excel ... 2、熟悉接口文档然后设计测试用例&am…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
算法250609 高精度
加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...

