Kubernetes 负载均衡器解决方案 MetalLB实践

Kubernetes 负载均衡解决方案 MetalLB实践

MetalLB 是一个用于在 Kubernetes 集群中提供外部 IP 地址的负载均衡器实现。

准备工作

1. 安装需知

安装 MetalLB 有一些前置条件:

  • Kubernetesv1.13.0 或者更新的版本

  • 集群中的 CNI 要能兼容 MetalLB,最新的兼容性参考NETWORK ADDON COMPATIBILITY

    Network addonCompatible
    AntreaYes (Tested on version 1.4 and 1.5)
    CalicoMostly (see known issues)
    CanalYes
    CiliumYes
    FlannelYes
    Kube-ovnYes
    Kube-routerMostly (see known issues)
    Weave NetMostly (see known issues)

    备注:

    常见的 Flannel、Cilium 等都是兼容的,Calico 的话大部分情况都兼容,BGP 模式下需要额外处理。因为 BGP 单 session 的限制,如果 CNI 插件为 Calico ,同时 Calico 也是使用的 BGP 模式,就会有冲突从而导致 MetalLB 无法正常工作。

  • 提供一些 IPv4 地址给 MetalLB 用于分配。

  • 当使用 BGP 操作模式时,你将需要一个或多个能够支持 BGP 协议的路由器。

  • L2 模式下需要各个节点间 7946 端口(TCP & UDP)需要互通。

最新信息参考:requirements

2. 本文部署的环境

确保你的 Kubernetes 集群已经部署并且运行正常。

root@master1:~# kubectl get node -o wide
NAME      STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
master1   Ready    control-plane   2d19h   v1.28.2   192.168.0.61   <none>        Ubuntu 24.04 LTS   6.8.0-36-generic   containerd://1.7.12
node1     Ready    <none>          2d19h   v1.28.2   192.168.0.62   <none>        Ubuntu 24.04 LTS   6.8.0-36-generic   containerd://1.7.12
node2     Ready    <none>          2d19h   v1.28.2   192.168.0.63   <none>        Ubuntu 24.04 LTS   6.8.0-36-generic   containerd://1.7.12

CNI插件及版本信息:

root@master1:~# calicoctl version
Client Version:    v3.28.0
Git commit:        413e6f559
Cluster Version:   v3.28.0
Cluster Type:      typha,kdd,k8s,operator,bgp,kubeadm

# calico使用bgp模式
root@master1:~# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+--------------+-------------------+-------+----------+-------------+
| 192.168.0.62 | node-to-node mesh | up    | 01:33:35 | Established |
| 192.168.0.63 | node-to-node mesh | up    | 02:48:04 | Established |
+--------------+-------------------+-------+----------+-------------+

IPv6 BGP status

root@master1:~# calicoctl get ippool -o wide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE     DISABLED   DISABLEBGPEXPORT   SELECTOR
default-ipv4-ippool   10.244.0.0/16   true   Never      CrossSubnet   false      false              all()

root@master1:~# kubectl get pod -n calico-system
NAME                                      READY   STATUS    RESTARTS         AGE
calico-kube-controllers-b7fb9d96c-pbf9s   1/1     Running   3 (80m ago)      4d18h
calico-node-gdsjw                         1/1     Running   30 (2m32s ago)   4d18h
calico-node-hvqg4                         1/1     Running   3 (80m ago)      4d18h
calico-node-rj9dd                         1/1     Running   3 (80m ago)      4d17h
calico-typha-55ccdf44bf-v2zmm             1/1     Running   3 (80m ago)      4d18h
calico-typha-55ccdf44bf-w5l8w             1/1     Running   3 (80m ago)      4d18h
csi-node-driver-bqvb7                     2/2     Running   6 (80m ago)      4d18h
csi-node-driver-cw59h                     2/2     Running   6 (80m ago)      4d18h
csi-node-driver-hbw2n                     2/2     Running   6 (80m ago)      4d18h

概念原理说明

1. Layer2模式

该部分的官方文档请参考:[layer2模式](https://metallb.universe.tf/concepts/layer2/)

以下时摘取部分进行翻译:

在 Layer 2 模式下,一个节点承担起向本地网络广告服务的责任。从网络的角度来看,这台机器的网络接口上似乎分配了多个 IP 地址。

在底层,MetalLB 响应 IPv4 服务的 ARP 请求和 IPv6 服务的 NDP 请求。

Layer 2 模式的主要优势是其普遍性:它可以在任何以太网网络上工作,无需特殊硬件,甚至不需要高级路由器。

负载均衡行为

在 Layer 2 模式下,所有针对服务 IP 的流量都会转发到一个节点,然后kube-proxy 会将流量分发到所有的服务 pod。

从这个意义上讲,Layer 2 并没有实现一个负载均衡器,而是实现了一种故障转移机制,以便在当前主节点由于某种原因失败时,其他节点可以接管。

如果主节点由于某种原因失败,故障转移是自动的:使用 memberlist 检测到失败节点,此时新节点接管失败节点的 IP 地址。

局限性

Layer 2 模式有两个主要限制需要注意:单节点瓶颈和潜在的故障转移速度慢。

单节点瓶颈

在 Layer 2 模式下,一个通过选举产生的主节点接收所有服务 IP 的流量。这意味着服务的入口带宽被限制在单个节点的带宽范围内。这是使用 ARP 和 NDP 引导流量的一个根本性限制。

潜在的故障转移速度慢

在故障转移方面,MetalLB 也实现了自动故障转移。目前的机制是通过 memberlist 这个基于 gossip 协议的成员和故障检测的库,其他节点检测到 Leader 故障后自动重新选举出新 Leader,新的 Leader 自动接管所有 ExternalIP 并发送大量二层数据包来通知客户端(也就是区域网中的其他节点) ExternalIP 的 MAC 地址变化。

根据官网文档描述,大部分主流操作系统的现代版本(Windows、Mac、Linux)都正确实现了 Layer 2 故障转移,问题只会出现在较旧或不常见的操作系统上。故障转移正常情况下会在几秒内完成,一般不会超过 10 秒。在更新完成前 ExternalIP 会无法访问。

L2 主节点选举的工作原理

给定负载均衡器 IP 的“主节点”(将要广播 IP 的节点)的选举是无状态的,其工作方式如下:

  1. 每个 speaker 收集给定 IP 的潜在广播者列表,考虑活跃的 speaker、外部流量策略、活跃的端点、节点选择器等因素。
  2. 每个 speaker 都进行相同的计算:获取“节点+VIP”元素的哈希值排序列表,并在自己是该列表的第一个条目时宣布服务。

2. BGP模式

该部分的官方文档请参考:bgp模式

在BGP模式下,集群中的每个节点都会与你的网络路由器建立BGP对等会话,并利用这个对等会话来通告集群外部服务的IP地址。

假设你的路由器配置支持多路径,这就能实现真正的负载均衡:MetalLB发布的路由彼此等价,除了它们的下一跳(nexthop)不同。这意味着路由器会同时使用所有下一跳,并在这之间进行负载均衡。

当数据包到达节点后,kube-proxy负责最后一跳的流量路由,将数据包定向到服务中特定的一个Pod上。

负载均衡行为

负载均衡的具体行为取决于你使用的具体路由器型号和配置,但通常的行为是基于包哈希值,按连接进行负载均衡。“按连接”指的是单个TCP或UDP会话的所有数据包都将被导向集群中的单一机器。流量的分发仅发生在不同的连接间,而不是在一个连接内的数据包之间。

将单个连接的数据包分散到多个集群节点会导致以下问题:

  • 将单个连接分散到多条路径上会导致线路上的数据包重排序,这对终端主机的性能影响巨大。

  • Kubernetes内部的节点间流量路由并不保证一致性。这意味着两个不同的节点可能会将同一连接的数据包路由到不同的Pod,导致连接失败。

局限性

BGP 模式最大的弊端就是不能优雅的处理节点下线。当集群中某个节点下线时,所有客户端对这个节点的连接都会被主动断开。

客户端一般会出现一个 Connection reset by peer 错误

同时由于是对每个数据包基于 hash 值进行负载均衡,因此对后端节点数是非常敏感的,这也是 BGP 的一个优点,故障转移非常快。

正因为 BGP 故障转移很快,反而引发了一个 BGP 模式的最大缺点:由于 BGP 会对每个数据包做负载均衡,在主机发生故障时会快速切换到新的主机上,从而引发节点变动时同一连接的不同数据包可能会发送到不同主机上导致网络导致的网络重排问题

比如第一个包转发到节点 A,然后处理第二个包时添加或故障了一个节点,按照新的节点数进行负载均衡计算,可能第二个数据包就被分到节点 B 了,节点 B 很明显是不能正确处理这个数据包的。

对客户端来说就是这次请求直接失败了。

解决该弊端的方法没有太理想的解决办法,只能尽量采取一些优化手段:

  • BGP路由器配置使用更稳定的ECMP哈希算法。比如“弹性ECMP”或“弹性LAG”。使用这样的算法极大地减少了后端节点更改时受影响的连接。
  • 将你的服务部署固定到特定的节点上,尽量少的增删节点。
  • 在流量“低谷期”进行服务部署的变更。
  • 将每个逻辑服务拆分为两个具有不同IP的Kubernetes服务,并借助DNS优雅地将用户流量从一个服务迁移到另一个服务。
  • 在客户端添加透明的重试逻辑,以优雅地从突然的断开中恢复。如果客户端是如移动应用或富单页Web应用这类应用,这种方法尤其有效。
  • 将你的服务置于入口控制器(ingress controller)之后。入口控制器本身可以使用MetalLB来接收流量,但在BGP和你的服务之间有一个有状态的层意味着你可以更改服务而不必担心。你只需要在更改入口控制器本身的部署时小心(例如,当增加更多的NGINX Pod来扩展规模时)。
  • 接受偶尔会有连接重置的爆发。对于低可用性的内部服务而言,这可能是可接受的现状。

部署 MetalLB

官方提供了好几种安装方式,yaml、helm、operator 等,这里使用 yaml 方式安装。

如果kube-proxy使用的是IPVS模式,在v1.14.2版本之后,需要启用strict ARP mode。

root@master1:~# kubectl edit configmap -n kube-system kube-proxy
...
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: true   # 启用strictARP
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    logging:
      flushFrequency: 0
      options:
        json:
          infoBufferSize: "0"
      verbosity: 0
    metricsBindAddress: ""
    mode: "ipvs"      # kube-proxy模式,默认为iptables
    nodePortAddresses: null
    oomScoreAdj: null
...

# 重启kube-proxy生效
kubectl rollout restart daemonset/kube-proxy -n kube-system

说明:

kube-proxy默认使用的是iptables转发模式,在大规模集群中,建议改为ipvs。如果当前转发模式是ipvs,启用严格的 ARP。

1. 创建 MetalLB 命名空间

kubectl create namespace metallb-system

2. 使用Manifest安装MetalLB

MetalLB 提供了一组清单文件来部署所需的组,使用如下命令部署:

curl https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml -O
kubectl apply -f metallb-native.yaml

查询官网文档获取最新的安装命令。

3. 验证安装

root@master1:~# kubectl get pods -n metallb-system
NAME                          READY   STATUS    RESTARTS      AGE
controller-56bb48dcd4-pp4w4   1/1     Running   2 (60m ago)   47h
speaker-4kfhv                 1/1     Running   1 (60m ago)   43h
speaker-5b5sq                 1/1     Running   7 (60m ago)   47h
speaker-wctd6                 1/1     Running   7 (60m ago)   47h

4. 配置 MetalLB

MetalLB 支持两种操作模式:Layer 2 模式和 BGP 模式。因为 BGP 对路由器有要求,POC测试时建议使用 Layer2 模式。

Layer2模式配置

Layer 2 模式是最简单的配置方式:在许多情况下,你不需要任何特定协议的配置,只需要 IP 地址。

Layer 2 模式不需要将 IP 绑定到你的工作节点的网络接口上。它通过直接响应本地网络上的 ARP 请求,向客户端提供机器的 MAC 地址来工作。

Layer2模式配置,首先创建一个IPAddressPool资源对象:

root@master1:~/metallb# cat ip-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.0.240-192.168.0.250 #分配给LB的IP池

备注

  1. IP地址池与集群IP位于同一个网段。
  2. 多个实例IP地址池可以共存,并且可以分配IPV4和IPV6地址。

应用创建资源:

kubectl apply -f ip-pool.yaml

创建一个广播声明,关联上面的 IP 池对象:

root@master1:~/metallb# cat advertise.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2adver
  namespace: metallb-system
spec:
  ipAddressPools:
    - ip-pool

应用创建资源:

kubectl apply -f advertise.yaml

说明:

如果不设置关联到 IPAdressPool,L2Advertisement 默认会关联所有可用的 IPAdressPool。

BGP模式配置

本文使用Layer2模式测试,后续补充BGP模式的POC验证。关于使用配置可以参考:https://metallb.universe.tf/configuration/#bgp-configuration

高级配置

Metal LB支持一些高级配置用于特殊的需求场景,详见官方文档:

  1. 区分不同的IP地址池:https://metallb.universe.tf/configuration/_advanced_ipaddresspool_configuration/#controlling-automatic-address-allocation

  2. 将IP地址池分配给指定的命名空间和服务:https://metallb.universe.tf/configuration/_advanced_ipaddresspool_configuration/#reduce-scope-of-address-allocation-to-specific-namespace-and-service

Layer2模式demo应用示例

1. 创建一个示例应用

为了验证 MetalLB 的配置是否正确,你可以创建一个简单的 Nginx 服务。

创建一个 nginx-deployment.yaml 文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

应用创建资源:

kubectl apply -f nginx-deployment.yaml

2. 暴露 Nginx 服务

创建一个 nginx-service.yaml 文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer

应用此服务:

kubectl apply -f nginx-service.yaml

3. 验证服务

检查服务的外部 IP 地址是否已分配:

kubectl get svc nginx-service

你应该会看到类似以下的输出:

root@master1:~/metallb# kubectl get svc nginx-service
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
nginx-service   LoadBalancer   10.101.212.243   192.168.0.240   80:30981/TCP   2d16h

在浏览器中访问 http://<EXTERNAL-IP>,例如 http://192.168.0.240,应该可以看到 Nginx 的默认页面。

或者使用curl测试:

root@master1:~/metallb# curl http://192.168.0.240
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

总结

1. MetalLB工作流程

MetalLB 做的工作可以分为两个部分:

  1. 地址分配:当创建 LoadBalancer Service 时,MetalLB 会为其分配 IP 地址。这个 IP 地址是从预先配置的 IP 地址库获取的。当 Service 删除后,已分配的 IP 地址会重新回到地址库。使用Controller实现地址分配,以 Deployment方式运行,用于监听 Service 的变更,分配/回收 IP 地址。

  2. 对外广播:分配了 IP 地址之后,需要让集群外的网络知道这个地址的存在。由Speaker实现地址对外广播,以 DaemonSet 方式运行,对外广播 Service 的 IP 地址。MetalLB 使用了标准的TCP/IP协议实现:ARP、NDP 或者 BGP。

  • 在 Layer 2 模式,使用 ARP(ipv4)/NDP(ipv6) 协议;
  • 在 BPG 模式,自然是使用 BGP 协议。

ARP(Address Resolution Protocol):是根据IP地址获取物理地址的一个TCP/IP协议。

NDP(neighbor Discovery protocol):ICMPv6的子协议,是IPV6协议体系中一个重要的基础协议,NDP替代了IPV4中的ARP。定义了使用ICMPv6报文实现地址解析,跟踪邻居状态,重复地址检测,路由器发现,以及重定向等功能。

具体的工作流如下:

  • Controller 负责监听 Service 变化并分配或回收 IP。

    当 Service 配置为 LoadBalancer 模式时,从 IP 池分配给到相应的 IP 地址并对该 IP 的生命周期进行管理。

    • 创建 Service 时(或者从非 LoadBalancer 类型修改为 LoadBalancer 类型)时从 IP 池选择一个 IP 并分配,
    • 删除 Service (或者从 LoadBalancer 类型修改为非 LoadBalancer 类型)时回收该 IP 到 IP 池
  • Speaker 则会依据选择的协议进行相应的广播或应答,实现 IP 地址的通信响应

    当业务流量通过 TCP/UDP 协议到达指定的 Node 时,由 Node 上面运行的 Kube-Proxy 组件对流量进行处理,并分发到对应服务的 Pod 上面。

    • 如果是 Layer2 模式 Speaker 就会响应 ARP(ipv4)/NDP(ipv6)请求。
    • 如果是 BGP 模式 Speaker 则发送 BGP 广播,将路由规则同步给 peer。

2. 两种模式的优缺点

Layer2 模式
  • 优点:通用性好,适用于任何网络环境,不需要特殊的硬件。
  • 缺点:单节点瓶颈和故障转移慢

Layer2 模式是一种基础、通用的实现,能用,而且易于使用,没有任何限制,但是局限性比较大。

BGP 模式
  • 优点:使用 BGP 可以在多节点间负载均衡,没有单节点瓶颈,同时故障转移很快。
  • 缺点: 需要支持 BGP 路由协议的软路由或者硬件 路由器设备。

参考资料

  1. MetalLB, bare metal load-balancer for Kubernetes
  2. Metal LB installation
  3. 裸机 Kubernetes 集群负载均衡器: MetalLB 简明教程 - (lixueduan.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/777476.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浏览器怎么抓包?Wireshark详细教程奉上!

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

Android 添加LBS辅助定位

1.软件需求&#xff1a; 某Android设备没有sim卡但其支持定位&#xff0c;客户需求为在已有的Android中添加LBS网络定位&#xff0c;用以辅助gps定位。 2.思路分析 首先看到这个需求笔者是比较懵逼的&#xff0c;秉持着客户是上帝的原则&#xff0c;笔者首先先了解了一下什么…

【深海王国】小学生都能玩的语音模块?ASRPRO打造你的第一个智能语音助手(7)

Hi~ (o^^o)♪, 各位深海王国的同志们&#xff0c;早上下午晚上凌晨好呀~ 辛勤工作的你今天也辛苦啦(/≧ω) 今天大都督继续为大家带来系列——小学生都能玩的语音模块&#xff0c;帮你一周内快速学会语音模块的使用方式&#xff0c;打造一个可用于智能家居、物联网领域的语音助…

通过SDK使用百度智能云的图像生成模型SDXL

登录进入百度智能云控制台&#xff0c;在模型广场按照图像生成类别进行筛选&#xff0c;可以找到Stable-Diffusion-XL模型。点击Stable-Diffusion-XL模型的API文档后在弹出的新页面下拉可以找到SDK调用的说明。 import qianfandef sdxl(file: str, prompt: str, steps: int 2…

商品分页,商品模糊查询

一、商品分页 引入分页 定义分页主件的参数 在请求url上拼接参数 定义改变当前页码后触发的事件&#xff0c;把当前页码的值给到分页表单&#xff0c;重新查询 二、商品查询&#xff08;以商品的名称查询name为例&#xff09; 引入elementplus的from表单组件 定义一个FormData…

Spring源码十二:事件发布源码跟踪

上一篇我们在Spring源码十一&#xff1a;事件驱动中&#xff0c;介绍了spring refresh方法的initMessageSource方法与initApplicationEventMulticaster方法&#xff0c;举了一个简单的例子进行简单的使用的Spring为我们提供的事件驱动发布的示例。这一篇我们将继续跟踪源码&…

创建React项目

使用 create-react-app快速搭建开发环境 create-react-app 是一个快速创建React开发环境的工具&#xff0c;底层由Webpack构建&#xff0c;封装了配置细节&#xff0c;开箱即用。 安装npx npx是一个由Node.js官方提供的用于快速执行npm包中的可执行文件的工具&#xff0c;np…

如何给gitlab其他访问者创建账号并增加权限

嗨&#xff0c;今天创建了项目之后&#xff0c;我想把项目链接发送给其他人&#xff0c;让他下载这个项目&#xff0c;结果发现对方打开显示登录的界面&#xff0c;没错&#xff0c;他要想使用这个git下载项目&#xff0c;首先他的有一个git账号 接下来我找有权限的相关人员给他…

C语言之常用内存函数以及模拟实现

目录 前言 一、memcpy的使用和模拟实现 二、memmove的使用和模拟实现 三、memset的使用和模拟实现 四、memcmp的使用和模拟实现 总结 前言 本文主要讲述C语言中常用的内存函数&#xff1a;memcpy、memmove、memset、memcmp。内容不多&#xff0c;除了了解如何使用&#x…

前端根据目录生成模块化路由routes

根据约定大于配置的逻辑&#xff0c;如果目录结构约定俗成&#xff0c;前端是可以根据目录结构动态生成路由所需要的 route 结构的&#xff0c;这个过程是要在编译时 进行&#xff0c;生成需要的代码&#xff0c;保证运行时的代码正确即可 主流的打包工具都有对应的方法读取文…

在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——聚合与搜索(三)

#在生产环境中部署Elasticsearch&#xff1a;最佳实践和故障排除技巧——聚合与搜索&#xff08;三&#xff09; 前言 文章目录 前言- 聚合和分析- 执行聚合操作- 1. 使用Java API执行聚合操作- 2. 使用CURL命令执行聚合操作- 1. 使用Java API执行度量操作- 2. 使用CURL命令执…

Java——继承(Inheritance)

一、继承简要介绍 1、继承是什么 在Java中&#xff0c;继承是一种面向对象编程的重要特性&#xff0c;它允许一个类&#xff08;子类或派生类&#xff09;继承另一个类&#xff08;父类或基类&#xff09;的属性和方法。继承的目的是实现代码的重用和设计的层次化。 子类通常…

探索LlamaIndex:如何用Django打造高效知识库检索

简介 LlamaIndex&#xff08;前身为 GPT Index&#xff09;是一个数据框架&#xff0c;为了帮助我们去建基于大型语言模型&#xff08;LLM&#xff09;的应用程序。 主要用于处理、构建和查询自定义知识库。 它支持多种数据源格式 excel&#xff0c;txt&#xff0c;pdf&…

DaViT(ECCV 2022,Microsoft)

paper&#xff1a;DaViT: Dual Attention Vision Transformers official implementation&#xff1a;https://github.com/dingmyu/davit third-party implementation&#xff1a;https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/davit.py 出发点…

独家揭秘!格行随身WiFi‘骄傲’宣言背后的震撼行业的真相!随身WiFi行业内黑马

近几年以来&#xff0c;随行WiFi产品呈现爆发式增长&#xff0c;随行WiFi的火爆&#xff0c;是技术进步带给消费者的一种“福利”&#xff0c;各大直播间也充斥着品牌各异的随身WiFi。但真正脱颖而出、赢得消费者信赖的优质品牌却凤毛麟角。而其中最受欢迎的格行随身WiFi也因设…

Java语言+后端+前端Vue,ElementUI 数字化产科管理平台 产科电子病历系统源码

Java语言后端前端Vue,ElementUI 数字化产科管理平台 产科电子病历系统源码 Java开发的数字化产科管理系统&#xff0c;已在多家医院实施&#xff0c;支持直接部署。系统涵盖孕产全程&#xff0c;包括门诊、住院、统计和移动服务&#xff0c;整合高危管理、智能提醒、档案追踪等…

Stream练习

运用点&#xff1a; 流内数据类型转换(map)、filter、limit、skip、concat(让两个流合并) 题目&#xff1a; 操作1、2&#xff1a; ArrayList<String> manList new ArrayList<>();ArrayList<String> womanList new ArrayList<>();Collections.addAl…

C++之static关键字

文章目录 前提正文多重定义extern关键字使用staticstatic 全局变量(在.cpp文件中定义)static变量存放在哪里static变量可不可以放在.h文件中 static 函数static局部变量static 成员变量static 成员函数 总结参考链接 前提 好吧&#xff0c;八股&#xff0c;我又回来了。这次想…

8.14 矢量图层面要素2.5D渲染

文章目录 前言2.5D渲染QGis设置面符号为2.5D二次开发代码实现2.5D 总结 前言 本章介绍矢量图层面要素2.5D渲染的使用说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 2.5D渲染 2.5D渲染可以将多边形渲染为类3D效果。 QGis设置面符号为2.5D 以"hou…

数据库7.4

第二次作业 1.登陆数据库 2.创建数据库zoo 3.修改数据库zoo字符集为gbk 4.选择当前数据库为zoo 5.查看创建数据库zoo信息 6.删除数据库zoo C:\Windows\System32>mysql -uroot -p20040830Nmx mysql> create database zoo; alter database zoo character set gbk; mys…