k8s二次开发-kubebuiler一键式生成deployment,svc,ingress
一 Kubebuilder环境搭建
注:必须在当前的K8S集群有 nginx这个ingressclass
root@k8s:~# kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 19h
1.1 下载kubebuilder
wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.3.0/kubebuilder_linux_amd64 -O /usr/local/sbin/kubebuilder --no-check-certificate
chmod +x /usr/local/sbin/kubebuilderkubebuilder version
Version: main.version{KubeBuilderVersion:"3.3.0", KubernetesVendor:"1.23.1", GitCommit:"47859bf2ebf96a64db69a2f7074ffdec7f15c1ec", BuildDate:"2022-01-18T17:03:29Z", GoOs:"linux", GoArch:"amd64"}
1.2 下载Golang
wget https://studygolang.com/dl/golang/go1.19.7.linux-amd64.tar.gztar -C /usr/local -xzf go1.19.7.linux-amd64.tar.gzvim /etc/profileexport PATH=$PATH:/usr/local/go/bin
export GO111MODULE=on
export GOPROXY=https://goproxy.cn,direct
export PATH=$PATH:/root/go/binroot@k8s:~# go version
go version go1.19.7 linux/amd64
1.3 编译golang需要的文件
以下只是一个 Demo和后续开发的项目无关
mkdir -p /usr/local/kubebuilder/elasticwebgo mod init elasticweb
kubebuilder init --domain jcrose.top
mkdir binkubebuilder create api \
--group elasticweb \
--version v1 \
--kind ElasticWeb# 安装controller-gen,这个需要先 执行kubebuilder create api 才会产生这个包的
cd /root/go/pkg/mod/sigs.k8s.io/controller-tools@v0.8.0/cmd/controller-gen
go build -o controller-gen main.go
mv controller-gen /usr/local/sbin
cp /usr/local/sbin/controller-gen /usr/local/kubebuilder/elasticweb/binmake install #第一次会失败,因为缺乏 kustomize # 安装kustomize
cd /root/go/pkg/mod/sigs.k8s.io/kustomize/kustomize/v3@v3.8.7
go build -o kustomize main.go
cp kustomize /usr/local/sbin
cp kustomize /usr/local/kubebuilder/elasticweb/binmake install kubectl get crds|grep jcrose
elasticwebs.elasticweb.jcrose.top 2023-04-09T14:25:18Z
安装启动容器的时候初始化的环境包
# 官方文档 https://github.com/kubernetes-sigs/controller-runtime/tree/main/tools/setup-envtest
# 安装setup-envtest
# cd /root/go/pkg/mod/sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20230403212152-53057ba616d1
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@release-0.17
cp /root/go/bin/setup-envtest /usr/local/sbin/
此时安装了 kustomize,controller-gen,setup-envtest 三个文件
二 初始化项目
kubebuilder init --domain jcrose.top
kubebuilder create api --group infra --version v1 --kind App
2.1 controllers/app_controller.go
/*
Copyright 2024.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package controllersimport ("context""fmt"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"apinetv1 "k8s.io/api/networking/v1""k8s.io/apimachinery/pkg/api/errors""k8s.io/apimachinery/pkg/api/resource"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/klog/v2"ctrl "sigs.k8s.io/controller-runtime""sigs.k8s.io/controller-runtime/pkg/client""sigs.k8s.io/controller-runtime/pkg/controller/controllerutil""sigs.k8s.io/controller-runtime/pkg/reconcile"infrav1 "jcrose/api/v1"
)// AppReconciler reconciles a App object
type AppReconciler struct {client.ClientScheme *runtime.Scheme//Log logr.Logger
}//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps/finalizers,verbs=update
//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the App object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.0/pkg/reconcile
func (r *AppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {ctx = context.Background()fmt.Println("Name", req.Name)fmt.Println("Namespace", req.Namespace)fmt.Println("NamespacedName", req.NamespacedName)//log := r.Log.WithValues("yunlizhi infra app", req.NamespacedName)// log.Info("1. start reconcile logic")// TODO(user): your logic hereinstance := &infrav1.App{}// 通过客户端工具查询,查询条件是err := r.Get(ctx, req.NamespacedName, instance)if err != nil {// 如果没有实例,就返回空结果,这样外部就不再立即调用Reconcile方法了if errors.IsNotFound(err) {klog.Info("2.1. instance not found, maybe removed")return reconcile.Result{}, nil}klog.Error(err, "2.2 error")// 返回错误信息给外部return ctrl.Result{}, err}klog.Info("3. instance : " + instance.String())// 查找deploymentdeployment := &appsv1.Deployment{}// 用客户端工具查询err = r.Get(ctx, req.NamespacedName, deployment)// 查找时发生异常,以及查出来没有结果的处理逻辑if err != nil {// 如果没有实例就要创建了if errors.IsNotFound(err) {klog.Info("4. deployment not exists")// 如果对QPS没有需求,此时又没有deployment,就啥事都不做了// 先要创建serviceif err = createServiceIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.2 error")// 返回错误信息给外部return ctrl.Result{}, err}// 立即创建deploymentif err = createDeploymentIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.3 error")// 返回错误信息给外部return ctrl.Result{}, err}if err = createIngressIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.3 error")// 返回错误信息给外部return ctrl.Result{}, err}// 如果创建成功就更新状态if err = updateStatus(ctx, r, instance); err != nil {klog.Error(err, "5.4. error")// 返回错误信息给外部return ctrl.Result{}, err}// 创建成功就可以返回了return ctrl.Result{}, nil} else {klog.Error(err, "7. error")// 返回错误信息给外部return ctrl.Result{}, err}}// 如果查到了deployment,并且没有返回错误,就走下面的逻辑klog.Info("11. update deployment's Replicas")// 通过客户端更新deploymentif err = r.Update(ctx, deployment); err != nil {klog.Error(err, "12. update deployment replicas error")// 返回错误信息给外部return ctrl.Result{}, err}klog.Info("13. update status")// 如果更新deployment的Replicas成功,就更新状态if err = updateStatus(ctx, r, instance); err != nil {klog.Error(err, "14. update status error")// 返回错误信息给外部return ctrl.Result{}, err}return ctrl.Result{}, nil}// SetupWithManager sets up the controller with the Manager.
func (r *AppReconciler) SetupWithManager(mgr ctrl.Manager) error {return ctrl.NewControllerManagedBy(mgr).For(&infrav1.App{}).Complete(r)
}func updateStatus(ctx context.Context, r *AppReconciler, App *infrav1.App) error {//log := r.Log.WithValues("func", "updateStatus")App.Status.TotalDomain = App.Spec.Domainif err := r.Status().Update(ctx, App); err != nil {klog.Error(err, "update instance error")return err}return nil
}func createDeploymentIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createDeployment")deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: app.Namespace,Name: app.Name,},Spec: appsv1.DeploymentSpec{Replicas: app.Spec.Replicas,Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": app.Spec.Project,},},Template: corev1.PodTemplateSpec{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": app.Spec.Project,},},Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: app.Spec.Project,Image: app.Spec.Image,ImagePullPolicy: "IfNotPresent",Ports: []corev1.ContainerPort{{Name: "http",Protocol: corev1.ProtocolTCP,ContainerPort: *app.Spec.Port,},},Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{"cpu": resource.MustParse("100m"),"memory": resource.MustParse("256Mi"),},Limits: corev1.ResourceList{"cpu": resource.MustParse("200m"),"memory": resource.MustParse("512Mi"),},},},},},},},}klog.Info("set reference")if err := controllerutil.SetControllerReference(app, deployment, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}klog.Info("start create deployment")if err := r.Create(ctx, deployment); err != nil {klog.Error(err, "create deployment error")return err}klog.Info("create deployment success")return nil
}func createServiceIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createService")service := &corev1.Service{}err := r.Get(ctx, req.NamespacedName, service)// 如果查询结果没有错误,证明service正常,就不做任何操作if err == nil {klog.Info("service exists")return nil}// 如果错误不是NotFound,就返回错误if !errors.IsNotFound(err) {klog.Error(err, "query service error")return err}// 实例化一个数据结构service = &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: app.Namespace,Name: app.Name,},Spec: corev1.ServiceSpec{Ports: []corev1.ServicePort{{Name: "http",Port: *app.Spec.Port,},},Selector: map[string]string{"app": app.Spec.Project,},Type: corev1.ServiceTypeNodePort,},}// 这一步非常关键!// 建立关联后,删除elasticweb资源时就会将deployment也删除掉klog.Info("set reference")if err := controllerutil.SetControllerReference(app, service, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}// 创建serviceklog.Info("start create service")if err := r.Create(ctx, service); err != nil {klog.Error(err, "create service error")return err}klog.Info("create service success")app.Status.TotalDomain = app.Spec.Domainerr = r.Status().Update(ctx, service)if err != nil {return err}return nil
}func createIngressIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createIngress")ingress := &apinetv1.Ingress{}err := r.Get(ctx, req.NamespacedName, ingress)// 如果查询结果没有错误,证明service正常,就不做任何操作if err == nil {klog.Info("ingress exists")return nil}// 如果错误不是NotFound,就返回错误if !errors.IsNotFound(err) {klog.Error(err, "query service error")return err}// 实例化一个数据结构ingress.Name = app.Nameingress.Namespace = app.NamespacepathType := apinetv1.PathTypePrefixicn := "nginx"ingress.Spec = apinetv1.IngressSpec{IngressClassName: &icn,Rules: []apinetv1.IngressRule{{Host: app.Spec.Domain,IngressRuleValue: apinetv1.IngressRuleValue{HTTP: &apinetv1.HTTPIngressRuleValue{Paths: []apinetv1.HTTPIngressPath{{Path: "/",PathType: &pathType,Backend: apinetv1.IngressBackend{Service: &apinetv1.IngressServiceBackend{Name: app.Name,Port: apinetv1.ServiceBackendPort{Number: *app.Spec.Port,},},},},},},},},},}// 这一步非常关键!// 建立关联后,删除elasticweb资源时就会将deployment也删除掉klog.Info("set reference")if err := controllerutil.SetControllerReference(app, ingress, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}// 创建serviceklog.Info("start create ingress")if err := r.Create(ctx, ingress); err != nil {klog.Error(err, "create service error")return err}klog.Info("create service success")return nil
}
2.2 api/v1/app_types.go
/*
Copyright 2023.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package v1import ("fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.// AppSpec defines the desired state of App
type AppSpec struct {// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster// Important: Run "make" to regenerate code after modifying this file// Foo is an example field of App. Edit app_types.go to remove/updateReplicas *int32 `json:"replicas,omitempty"`Image string `json:"image,omitempty"`Port *int32 `json:"port,omitempty"`Project string `json:"project,omitempty"`Domain string `json:"domain,omitempty"`
}// AppStatus defines the observed state of App
type AppStatus struct {// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster// Important: Run "make" to regenerate code after modifying this fileTotalStatus string `json:"totalStatus"`TotalDomain string `json:"totalDomain"`
}//+kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".spec.replicas",description="pod的个数"
// +kubebuilder:printcolumn:name="Domain",type="string",JSONPath=".spec.domain",description="ingress的域名"
// +kubebuilder:printcolumn:name="Image",type="string",JSONPath=".spec.image",description="app的镜像地址"
//+kubebuilder:subresource:status// App is the Schema for the apps API
type App struct {metav1.TypeMeta `json:",inline"`metav1.ObjectMeta `json:"metadata,omitempty"`Spec AppSpec `json:"spec,omitempty"`Status AppStatus `json:"status,omitempty"`
}//+kubebuilder:object:root=true// AppList contains a list of App
type AppList struct {metav1.TypeMeta `json:",inline"`metav1.ListMeta `json:"metadata,omitempty"`Items []App `json:"items"`
}func init() {SchemeBuilder.Register(&App{}, &AppList{})
}func (in *App) String() string {return fmt.Sprintf("Image [%s], Port [%d], AppName [%s]",in.Spec.Image,*(in.Spec.Port),in.Spec.Project)
}
2.3 main.go
/*
Copyright 2023.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package mainimport ("flag""os"// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)// to ensure that exec-entrypoint and run can make use of them._ "k8s.io/client-go/plugin/pkg/client/auth""k8s.io/apimachinery/pkg/runtime"utilruntime "k8s.io/apimachinery/pkg/util/runtime"clientgoscheme "k8s.io/client-go/kubernetes/scheme"ctrl "sigs.k8s.io/controller-runtime""sigs.k8s.io/controller-runtime/pkg/healthz""sigs.k8s.io/controller-runtime/pkg/log/zap"infrav1 "yunlizhi/api/v1""yunlizhi/controllers"//+kubebuilder:scaffold:imports
)var (scheme = runtime.NewScheme()setupLog = ctrl.Log.WithName("setup")
)func init() {utilruntime.Must(clientgoscheme.AddToScheme(scheme))utilruntime.Must(infrav1.AddToScheme(scheme))//+kubebuilder:scaffold:scheme
}func main() {var metricsAddr stringvar enableLeaderElection boolvar probeAddr stringflag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")flag.BoolVar(&enableLeaderElection, "leader-elect", false,"Enable leader election for controller manager. "+"Enabling this will ensure there is only one active controller manager.")opts := zap.Options{Development: true,}opts.BindFlags(flag.CommandLine)flag.Parse()ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{Scheme: scheme,MetricsBindAddress: metricsAddr,Port: 9443,HealthProbeBindAddress: probeAddr,LeaderElection: enableLeaderElection,LeaderElectionID: "dcd31429.yunlizhi.cn",})if err != nil {setupLog.Error(err, "unable to start manager")os.Exit(1)}if err = (&controllers.AppReconciler{Client: mgr.GetClient(),Log: ctrl.Log.WithName("controllers").WithName("app"),Scheme: mgr.GetScheme(),}).SetupWithManager(mgr); err != nil {setupLog.Error(err, "unable to create controller", "controller", "App")os.Exit(1)}//+kubebuilder:scaffold:builderif err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {setupLog.Error(err, "unable to set up health check")os.Exit(1)}if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {setupLog.Error(err, "unable to set up ready check")os.Exit(1)}setupLog.Info("starting manager")if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {setupLog.Error(err, "problem running manager")os.Exit(1)}
}
三 部署 jcrose.top operator
3.1 修改Dockerfile,新增一个GOPROXY提高编译速度
# Build the manager binary
FROM golang:1.17 as builderENV GOPROXY=https://goproxy.cn,direct #主要是这一行WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download# Copy the go source
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM katanomi/distroless-static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532ENTRYPOINT ["/manager"]
3.2 部署
# 制作推送镜像至阿里云,需要先登录
# 这个需要在阿里云的镜像仓库创建这个仓库make docker-build docker-push IMG=registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2# kind可以直接导入
kind load docker-image registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2make install
make manifests #配置RBAC权限# 部署controller
make deploy IMG=registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2
3.3 资源文件
apiVersion: infra.jcrose.top/v1
kind: App
metadata:name: jcrose-sample
spec:# Add fields herereplicas: 1image: registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2port: 8080domain: tomcat.jcrose.comproject: tomcat
四 最终效果
root@k8s:~# kubectl get app
NAME REPLICAS DOMAIN IMAGE
jcrose-sample 1 tomcat.jcrose.com registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2
root@k8s:~# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
jcrose-sample nginx tomcat.jcrose.com 10.106.189.253 80 27m
root@k8s:~# kubectl get app
NAME REPLICAS DOMAIN IMAGE
jcrose-sample 1 tomcat.jcrose.com registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2
root@k8s:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jcrose-controller-manager-metrics-service ClusterIP 10.102.238.108 <none> 8443/TCP 20h
jcrose-sample NodePort 10.105.10.100 <none> 8080:20408/TCP 32m
相关文章:
k8s二次开发-kubebuiler一键式生成deployment,svc,ingress
一 Kubebuilder环境搭建 注:必须在当前的K8S集群有 nginx这个ingressclass rootk8s:~# kubectl get ingressclass NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx <none> 19h1.1 下载kubebuilder wget https://gi…...
Flutter 状态管理新境界:多Provider并行驱动UI
前言 在上一篇文章中,我们讨论了如何使用 Provider 在 Flutter 中进行状态管理。 本篇文章我们来讨论如何使用多个 Provider。 在 Flutter 中,使用 Provider 管理多个不同的状态时,你可以为每个状态创建一个单独的 ChangeNotifierProvider…...
标识符和关键字的区别是什么,常用的关键字有哪些?自增自减运算符,移位运算符continue、break、return的区别是什么?
标识符和关键字的区别是什么,常用的关键字有哪些? 标识符标识符就是当我们给变量,方法,类命名时候的名字,而被赋予特殊含义的标识符就是关键字。例如生活中,当我们需要开一家店时候,我们不能将…...
在VS Code上搭建Vue项目教程(Vue-cli 脚手架)
1.前期环境准备 搭建Vue项目使用的是Vue-cli 脚手架。前期环境需要准备Node.js环境,就像Java开发要依赖JDK环境一样。 1.1 Node.js环境配置 1)具体安装步骤操作即可: npm 安装教程_如何安装npm-CSDN博客文章浏览阅读836次。本文主要在Win…...
AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理
AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理 目录 AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理 一、简单介绍 二、零样本学习 (Zero-shot Learning) 和少样本学习 (Few-shot Learning) 1、零样本学…...
Docker 和 k8s 之间是什么关系?
Docker 简介 Docker 功能: Docker 是一款可以将程序和环境打包并运行的工具软件。通过 Docker,可以将程序及其依赖环境打包,确保在不同操作系统上一致的运行效果。 环境一致性问题: 程序依赖于特定的环境,不同操作系统…...
敲详细的springframework-amqp-rabbit源码解析
看源码时将RabbitMQ的springframework-amqp-rabbit和spring-rabbit的一套区分开,springboot是基于RabbitMQ的Java客户端建立了简便易用的框架。 springboot的框架下相对更多地使用消费者Consumer和监听器Listener的概念,这两个概念不注意区分容易混淆。…...
Telegram Bot、小程序开发(三)Mini Apps小程序
文章目录 一、Telegram Mini Apps小程序二、小程序启动方式三、小程序开发小程序调试模式初始化小程序Keyboard Button Mini Apps 键盘按钮小程序【依赖具体用户信息场景,推荐】**Inline Button Mini Apps内联按钮小程序**initData 的自动传递使用内联菜单时候哪些参数会默认传…...
Django F()函数
F()函数的作用 F()函数在Django中是一个非常强大的工具,主要用于在查询表达式中引用模型的字段。它允许你在数据库层面执行各种操作,而无需将数据加载到Python内存中。这不仅提高了性能,还允许你利用数据库的优化功能。 字段引用 在查询表达…...
GraphRAG的实践
好久没有体验新技术了,今天来玩一下GraphRAG 顾名思义,一种检索增强的方法,利用图谱来实现RAG 1.配置环境 conda create -n GraphRAG python3.11 conda activate GraphRAG pip install graphrag 2.构建GraphRAG mkdir -p ./ragtest/i…...
自动驾驶三维车道线检测系列—LATR: 3D Lane Detection from Monocular Images with Transformer
文章目录 1. 概述2. 背景介绍3. 方法3.1 整体结构3.2 车道感知查询生成器3.3 动态3D地面位置嵌入3.4 预测头和损失 4. 实验评测4.1 数据集和评估指标4.2 实验设置4.3 主要结果 5. 讨论和总结 1. 概述 3D 车道线检测是自动驾驶中的一个基础但具有挑战性的任务。最近的进展主要依…...
守护动物乐园:视频AI智能监管方案助力动物园安全与秩序管理
一、背景分析 近日,某大熊猫参观基地通报了4位游客在参观时,向大熊猫室外活动场内吐口水的不文明行为。这几位游客的行为违反了入园参观规定并可能对大熊猫造成严重危害,已经被该熊猫基地终身禁止再次进入参观。而在此前,另一熊猫…...
FairGuard游戏加固入选《嘶吼2024网络安全产业图谱》
2024年7月16日,国内网络安全专业媒体——嘶吼安全产业研究院正式发布《嘶吼2024网络安全产业图谱》(以下简称“产业图谱”)。 本次发布的产业图谱,共涉及七大类别,127个细分领域。全面展现了网络安全产业的构成和重要组成部分,探…...
数据仓库事实表
数据仓库中的三种常见事实表类型:事务事实表、周期快照事实表和累积快照事实表 事务事实表: 事务事实表是记录事务级别数据的事实表。它记录了每个事务发生的具体度量指标,如销售金额、数量等。事务事实表的优势在于能够提供详细的事务级别…...
LeetCode题练习与总结:两数之和Ⅱ-输入有序数组--167
一、题目描述 给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 < index1 < index…...
在 Java 中,怎样设计一个可扩展且易于维护的微服务架构?
在Java中设计一个可扩展且易于维护的微服务架构,可以考虑以下几个方面: 模块化设计:将应用拆分为多个小的、独立的模块,每个模块负责处理特定的业务逻辑。每个模块可以独立开发、测试和部署,增加或替换模块时不会影响其…...
零基础入门鸿蒙开发 HarmonyOS NEXT星河版开发学习
今天开始带大家零基础入门鸿蒙开发,也就是你没有任何编程基础的情况下就可以跟着石头哥零基础学习鸿蒙开发。 目录 一,为什么要学习鸿蒙 1-1,鸿蒙介绍 1-2,为什么要学习鸿蒙 1-3,鸿蒙各个版本介绍 1-4࿰…...
Chromium CI/CD 之Jenkins实用指南2024-在Windows节点上创建任务(九)
1. 引言 在现代软件开发流程中,持续集成(CI)和持续交付(CD)已成为确保代码质量和加速发布周期的关键实践。Jenkins作为一款广泛应用的开源自动化服务器,通过其强大的插件生态系统和灵活的配置选项…...
ceph进程网卡绑定逻辑
main() //如osd进程,是ceph_osd.cc文件的main函数;mon进程,是ceph_mon.cc文件的main函数 -->pick_addresses() // 会读取"cluster_network_interface"和"public_network_interface"这两个配置项来过滤ip ---->fill…...
学习opencv
初步学习可以参考: OpenCV学习之路(附加资料分享)_opencv资料-CSDN博客 【OpenCV】OpenCV常用函数合集【持续更新】_opencv函数手册-CSDN博客 整体框架可以参考: OpenCV学习指南:从零基础到全面掌握(零…...
利用双端队列 实现二叉树的非递归的中序遍历
双端队列:双向队列:支持插入删除元素的线性集合。 java官方文档推荐用deque实现栈(stack)。 pop(): 弹出栈中元素,也就是返回并移除队头元素,等价于removeFirst(),如果队列无元素,则…...
昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要
昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要 文章目录 昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要数据集创建数据集数据预处理Tokenizer 模型构建构建GPT2ForSummarization模型动态学习率 模型训练模型推理总结打卡 数据集 实验使用nlpcc2017摘要数…...
科研绘图系列:R语言circos图(circos plot)
介绍 Circos图是一种数据可视化工具,它以圆形布局展示数据,通常用于显示数据之间的关系和模式。这种图表特别适合于展示分层数据或网络关系。Circos图的一些关键特点包括: 圆形布局:数据被组织在一个或多个同心圆中,每个圆可以代表不同的数据维度或层次。扇区:每个圆被划…...
追踪Conda包的踪迹:深入探索依赖关系与管理
追踪Conda包的踪迹:深入探索依赖关系与管理 Conda作为Python和其他科学计算语言的包管理器,不仅提供了安装、更新和卸载包的功能,还有一个强大的包跟踪功能,帮助用户理解包之间的依赖关系和管理环境。本文将详细解释如何在Conda中…...
苹果电脑pdf合并软件 苹果电脑合并pdf 苹果电脑pdf怎么合并
在数字化办公日益普及的今天,pdf文件因其跨平台兼容性强、格式稳定等特点,已经成为工作、学习和生活中不可或缺的文件格式。然而,我们常常面临一个问题:如何将多个pdf文件合并为一个?这不仅有助于文件的整理和管理&…...
axios(ajax请求库)
json-server(搭建http服务) json-server用来快速搭建模拟的REST API的工具包 使用json-server 下载:npm install -g json-server创建数据库json文件:db.json开启服务:json-srver --watch db.json axios的基本使用 <!doctype html>…...
Ideal窗口中左右侧栏消失了
不知道大家在工作过程中有没有遇到过此类问题,不论是Maven项目还是Gradle项目,突然发现Ideal窗口右侧图标丢失了,同事今天突然说大象图标不见了,不知道怎样刷新gradle。 不要慌张,下面提供一些解决思路: 1…...
麦芒30全新绽放,中国电信勾勒出AI手机的新方向
高通总裁兼CEO克里斯蒂亚诺阿蒙曾在媒体采访时表示:2024年将成为全球AI手机元年,生成式AI正在“非常快”的进入手机。 把大模型装进手机,由此成了智能终端演进的新方向。三星、华为、OPPO、小米等品牌动作频频,纷纷抢滩AI手机市场…...
数据结构之初始二叉树(3)
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 二叉树的基本操作 通过上篇文章的学习,我们简单的了解了二叉树的相关操作。接下来就是有…...
egret 白鹭的编译太慢了 自己写了一个
用的swc 他会检测git的改变 const simpleGit require(simple-git); const fs require(fs); const path require(path); // 初始化 simple-git const swc require(swc/core); const baseDir D:\\project; const gameDir game\\module\\abcdefg; const gitDir D:\\projec…...
天水做网站的公司/网站建设合同模板
相信很多从事js开发的朋友都或多或少了解一些有关js闭包(closure)的知识。 本篇文章是从小编个人角度,简单地介绍一下有关js闭包(closure)的相关知识。目的是帮助一些对js开发经验不是很多的朋友,使他们可以…...
网站维护步骤/促销活动推广方法有哪些
Nginx 配置反向代理和负载均衡 前言 这段时间在重新搞自己阿里云服务器上的博客,想着使用docker来搞一下方便后期“移植”,所以也顺带玩了一下nginx(我自己服务器实际上是用不到nginx的,只是这里纯属放假因为疫情出不去没事干搞着…...
网站备案申请流程/seo优化的技巧
描述 Description Bessie那惨无人道的二年级老师搞了一个有 N (1 < N < 100) 个正整数 I (1 < I < 10^60) 的表叫Bessie去判断“奇偶性”(这个词语意思向二年级的学生解释,就是“这个数是单数,还是双数啊?”…...
做淘宝客的网站需要备案吗/seo索引擎优化
自学PMP报考--考试全流程:如何自学通过PMP? PMP考试是需要35PDU才可以报名的,如果你要自学就可以在某宝上购买PDU,但是个人不建议(PDU证明一般是需要授权培训机构提供,在某宝买的第一不知道是否正规,第二…...
网站建站对象/快速搭建网站的工具
K-means聚类算法(事先数据并没有类别之分!所有的数据都是一样的)1、概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成…...
网站建设收费标准市场/网站统计数据
原创!ngxtop-监控nginx的利器!!! 无论名称还是界面,ngxtop的灵感均源自大名鼎鼎的top命令.ngxtop的功能就是,分析Nginx访问日志文件(以及其他日志文件,比如Apache2日志),并通过类似top的界面,实时显示分析后所得的结果.你可能吹嘘自己的综合监控工具拥有…...