如何借助Kafka持久化存储K8S事件数据?

大家应该对 Kubernetes Events 并不陌生,特别是当你使用 kubectl describe 命令或 Event API 资源来了解集群中的故障时。
 

$ kubectl get events

15m         Warning   FailedCreate                                                                                                      replicaset/ml-pipeline-visualizationserver-865c7865bc    

Error creating: pods "ml-pipeline-visualizationserver-865c7865bc-" is forbidden: error looking up service account default/default-editor: serviceaccount "default-editor" not found

 

尽管这些信息十分有用,但它只是临时的,保留时间最长为30天。如果出于审计或是故障诊断等目的,你可能想要把这些信息保留得更久,比如保存在像 Kafka 这样更持久、高效的存储中。然后你可以借助其他工具(如 Argo Events)或自己的应用程序订阅 Kafka 主题来对某些事件做出响应。
 

构建K8s事件处理链路

我们将构建一整套 Kubernetes 事件处理链路,其主要构成为:

  • Eventrouter,开源的 Kubernetes event 处理器,它可以将所有集群事件整合汇总到某个 Kafka 主题中。
  • Strimzi Operator,在 Kubernetes 中轻松管理 Kafka broker。
  • 自定义 Go 二进制文件以将事件分发到相应的 Kafka 主题中。
     

为什么要把事件分发到不同的主题中?比方说,在集群的每个命名空间中存在与特定客户相关的 Kubernetes 资产,那么在使用这些资产之前你当然希望将相关事件隔离开。
 

本示例中所有的配置、源代码和详细设置指示都已经放在以下代码仓库中:

 

 

创建 Kafka broker 和主题

我选择使用 Strimzi(strimzi.io/) 将 Kafka 部署到 Kubernetes 中。简而言之,它是用于创建和更新 Kafka broker 和主题的。你可以在官方文档中找到如何安装该 Operator 的详细说明:

 

首先,创建一个新的 Kafka 集群:

apiVersion: kafka.strimzi.io/v1beta1
kind: Kafka
metadata:
  name: kube-events
spec:
  entityOperator:
    topicOperator: {}
    userOperator: {}
  kafka:
    config:
      default.replication.factor: 3
      log.message.format.version: "2.6"
      offsets.topic.replication.factor: 3
      transaction.state.log.min.isr: 2
      transaction.state.log.replication.factor: 3
    listeners:
    - name: plain
      port: 9092
      tls: false
      type: internal
    - name: tls
      port: 9093
      tls: true
      type: internal
    replicas: 3
    storage:
      type: jbod
      volumes:
      - deleteClaim: false
        id: 0
        size: 10Gi
        type: persistent-claim
    version: 2.6.0
  zookeeper:
    replicas: 3
    storage:
      deleteClaim: false
      size: 10Gi
      type: persistent-claim

 

然后创建 Kafka 主题来接收我们的事件:

apiVersion: kafka.strimzi.io/v1beta1
kind: KafkaTopic
metadata:
  name: cluster-events
spec:
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824
  partitions: 1
  replicas: 1

 

设置 EventRouter

在本教程中使用 kubectl apply 命令即可,我们需要编辑 router 的配置,以指明我们的 Kafka 端点和要使用的主题:

apiVersion: v1
data:
  config.json: |-
    {
      "sink": "kafka",
      "kafkaBrokers": "kube-events-kafka-bootstrap.kube-events.svc.cluster.local:9092",
      "kafkaTopic": "cluster-events"
    }
kind: ConfigMap
metadata:
  name: eventrouter-cm

 

验证设置是否正常工作

我们的 cluster-events Kafka 的主题现在应该收到所有的事件。最简单的方法是在主题上运行一个 consumer 来检验是否如此。为了方便期间,我们使用我们的一个 Kafka broker pods,它已经有了所有必要的工具,你可以看到事件流:

kubectl -n kube-events exec kube-events-kafka-0 -- bin/kafka-console-consumer.sh \
  --bootstrap-server kube-events-kafka-bootstrap:9092 \
  --topic kube-events \
  --from-beginning
{"verb":"ADDED","event":{...}}
{"verb":"ADDED","event":{...}}
...

 

编写 Golang 消费者

现在我们想将我们的 Kubernetes 事件依据其所在的命名空间分发到多个主题中。我们将编写一个 Golang 消费者和生产者来实现这一逻辑:

  • 消费者部分在 cluster-events 主题上监听传入的集群事件
  • 生产者部分写入与事件的命名空间相匹配的 Kafka 主题中
     

如果为Kafka配置了适当的选项(默认情况),就不需要特地创建新的主题,因为 Kafka 会默认为你创建主题。这是 Kafka 客户端 API 的一个非常酷的功能。

p, err := kafka.NewProducer(cfg.Endpoint)
if err != nil {
        sugar.Fatal("cannot create producer")
}
defer p.Close()

c, err := kafka.NewConsumer(cfg.Endpoint, cfg.Topic)
if err != nil {
        sugar.Fatal("cannot create consumer")
}
defer c.Close()

run := true
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
        sig := <-sigs
        sugar.Infof("signal %s received, terminating", sig)
        run = false
}()

var wg sync.WaitGroup
go func() {
        wg.Add(1)
        for run {
                data, err := c.Read()
                if err != nil {
                        sugar.Errorf("read event error: %v", err)
                        time.Sleep(5 * time.Second)
                        continue
                }
                if data == nil {
                        continue
                }
                msg, err := event.CreateDestinationMessage(data)
                if err != nil {
                        sugar.Errorf("cannot create destination event: %v", err)
                }
                p.Write(msg.Topic, msg.Message)
        }
        sugar.Info("worker thread done")
        wg.Done()
}()

wg.Wait()

 

完整代码在此处:

 

当然还有更高性能的选择,这取决于预计的事件量和扇出(fanout)逻辑的复杂性。对于一个更强大的实现,使用 Spark Structured Streaming 的消费者将是一个很好的选择。
 

部署消费者

构建并将二进制文件推送到 Docker 镜像之后,我们将它封装为 Kubernetes deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: events-fanout
  name: events-fanout
spec:
  replicas: 1
  selector:
    matchLabels:
      app: events-fanout
  template:
    metadata:
      labels:
        app: events-fanout
    spec:
      containers:
        - image: emmsys/events-fanout:latest
          name: events-fanout
          command: [ "./events-fanout"]
          args:
            - -logLevel=info
          env:
            - name: ENDPOINT
              value: kube-events-kafka-bootstrap:9092
            - name: TOPIC
              value: cluster-events

 

检查目标主题是否创建

现在,新的主题已经创建完成:

kubectl -n kube-events get kafkatopics.kafka.strimzi.io -o name

kafkatopic.kafka.strimzi.io/cluster-events
kafkatopic.kafka.strimzi.io/kube-system
kafkatopic.kafka.strimzi.io/default
kafkatopic.kafka.strimzi.io/kafka
kafkatopic.kafka.strimzi.io/kube-events

 

你会发现你的事件根据其命名空间整齐地存储在这些主题中。
 

总结

访问 Kubernetes 历史事件日志可以使你对 Kubernetes 系统的状态有了更好的了解,但这单靠 kubectl 比较难做到。更重要的是,它可以通过对事件做出反应来实现集群或应用运维自动化,并以此来构建可靠、反应灵敏的软件。
 

原文链接:
http://hackernoon.com/monitor-your-kubernetes-cluster-events-with-eventrouter-golang-and-kafka-wh2a35l0

本文转载于网络 如有侵权请联系删除

相关文章

  • 齐博建站指南(艾戈勒)

    大家好,又见面了,我是你们的朋友全栈君。齐博建站指南使用手册 http://www.qibosoft.com/help/<?phpinclude(“../head.htm”);?><?phpinclude(“../../foot.htm”);?>/template/default/list_tpl1、新建风格:template/XXXdata/style下新建XXX.php2、需要全部静态的话,需要录入php标识的头尾3、加载list模块(列表模块)<!–includeEOT;if($listdb){@include(“$listTPL”);}print<<<EOTinclude–>4、编码选用gb23125、建站从菜单开始——头部和尾制作模板——中间内容加入php标识的头尾即可调用齐博标签在首页加入$label[index_c1]标签可进行可视化操作注:$label[自定义]6、齐博标签使用说明!!!{$webdb[www_url]}指整站访问网址 {$title}指标题 {$url}指超级链接地址  {$aid}指文章ID {$

  • Objective-C Runtime编程指南(2)

    苹果官方文档Objective-CRuntimeProgrammingGuide六、类型编码为了帮助运行时系统,编译器将字符串中每个方法的返回值和参数类型进行编码,并将字符串与方法选择器相关联。它使用的编码方案在其他上下文中也是有用的,所以通过@encode()编译器指令公开可用。当给定类型规范时,@encode()返回一个编码该类型的字符串。这个类型可以是一个基本的类型,比如int,指针,带标签的结构体或联合体,或者是一个类名,实际上,它可以用作Csizeof()运算符的参数。char*buf1=@encode(int**); char*buf2=@encode(structkey); char*buf3=@encode(Rectangle);复制下表列出了类型代码。请注意,它们中的许多与用于存档或分发的对象编码时使用的代码重叠。但是,这里列出的代码在编写代码时不能使用,并且在编写不是由@encode()生成的代码时,可能需要使用代码。重要:Objective-C不支持longdouble类型.@encode(longdouble)返回d,与double一样。数组的类型代码用方括号括

  • 为什么MySQL不推荐使用子查询和join

    来源:cnblogs.com/liboware/p/12740901.html1.对于mysql,不推荐使用子查询和join是因为本身join的效率就是硬伤,一旦数据量很大效率就很难保证,强烈推荐分别根据索引单表取数据,然后在程序里面做join,merge数据。2.子查询就更别用了,效率太差,执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,这里多了一个创建和销毁临时表的过程。3.如果是JOIN的话,它是走嵌套查询的。小表驱动大表,且通过索引字段进行关联。如果表记录比较少的话,还是OK的。大的话业务逻辑中可以控制处理。4.数据库是最底层的,瓶颈往往是数据库。建议数据库只是作为数据store的工具,而不要添加业务上去。一、应用层关联的优势让缓存的效率更高。许多应用程序可以方便地缓存单表查询对应的结果对象。如果关联中的某个表发生了变化,那么就无法使用查询缓存了,而拆分后,如果某个表很少改变,那么基于该表的查询就可以重复利用查询缓存结果了。将查询分解后,执行单个查询可以减少锁的竞争。在应用层做关联,可以更容易对数据库进行拆分,更容易做到高

  • SAP UI5 JavaScript文件的lazy load - 懒加载

    CreatedbyWang,Jerry,lastmodifiedonMay18,2016

  • 质量4.0 -行业4.0时代的透明产品质量监管(CS AI)

    渐进的数字化正在改变许多工业部门的游戏。关注产品质量这个所谓的行业4.0的主要盈利驱动力将是整个供应链上的横向信息集成。因此,欧洲RFCS项目“质量4.0”旨在开发一个适应性平台,该平台发布产品质量决策,并提供可与客户单独交换的高可靠性定制信息。在这种情况下,机器学习将用于检测质量数据中的异常值。本文讨论了中间项目结果和迄今为止为质量信息的横向集成开发的概念。原文题目:Quality4.0-TransparentproductqualitysupervisionintheageofIndustry4.0 原文:Progressivedigitalizationischangingthegameofmanyindustrialsectors.FocusingonproductqualitythemainprofitabilitydriverofthissocalledIndustry4.0willbethehorizontalintegrationofinformationoverthecompletesupplychain.Therefore,theEuropeanRFCSprojec

  • 工业互联网的逻辑到底是什么

    工业互联网,是相对“消费互联网”提出的概念。在消费互联网时期,互联网技术已经初步展现了其技术魅力,既创造了巨大的经济价值,又再次点燃了人类对于社会变革的梦想。正是由于消费互联网的巨大魅力,在工业互联网概念产生之后,人类社会也对工业互联网寄予了巨大的厚望。文/黄成甲工业互联网与消费互联网工业互联网是互联网发展的新领域,是在互联网基础上,面向实体经济应用的演进升级。我们通常所说的互联网一般指消费互联网,与之相比,工业互联网的主要差别:1.连接对象不同。消费互联网主要是连接人、应用、场景、消费,而工业互联网是要实现人、机、物等工业经济生产要素和上下游业务流程重大范围的连接,连接的种类、数量更多,场景更复杂。2.技术要求不同。消费互联网对网络时延、可靠性等要求相对不是特别严格,但工业互联网在网络性能上要求时间更低、可靠性更强,同时由于直接涉及工业生产,工业互联网的安全性要求更高。3.发展模式不同。消费互联网的应用门槛相对较低,发展模式可复制性也强。完全由互联网企业巨头主导驱动发展。工业互联网涉及应用的行业标准比较杂,专业化程度比较高,很难找到普适性的发展模式。同时消费互联网产业属于轻资产,投资

  • 【机器学习】Adaboost

    本文介绍了集成学习中Boosting的代表算法Adaboost。首先介绍了Adaboost的Boosting思想:1)学习器的投票权重,2)更新样本权重,巧妙之处在于这两个权重的设计使得Adaboost如此优美。然后介绍了Adaboost的前向加法思想,即不断拟合上一次分类器的损失。最后以前向加法模型中的特例(二分类)导出Adaboost的指数损失理解,再次回归到Adaboost的学习器权重和样本更新权重为何如此设计。作者|文杰编辑|yuquanleAdaboostAdaboost的Boosting理解Adaboost是集成学习中Boosting方式的代表。多个基学习器其串行执行,下一个学习器基于上一个学习器的经验,通过调整样本的权重,使得上一个错分的样本在下一个分类器更受重视而达到不断提升的效果。Adaboost集成多个学习器的关键在两点:设置基学习器的权重: 调整样本的权重: 相对随机森林的BootstrapSampling重采样技术,可以看出Adaboost的权重调整是有目的性,基于上一个学习器的经验,这也导致Adaboost在基学习器层是串行的。值得探讨的是权重为何如此设置?A

  • 工业镜头和民用镜头的区别在哪里?

    本文转载自:新机器视觉一、工业镜头的特点及分类 光学镜头一般称为摄像镜头或摄影镜头,简称镜头,其功能就是光学成像。镜头是机器视觉系统中的重要组件,对成像质量有着关键性的作用,它对成像质量的几个最主要指标都有影响,包括:分辨率、对比度、景深及各种像差。镜头不仅种类繁多,而且质量差异也非常大,但一般用户在进行系统设计时往往对镜头的选择重视不够,导致不能得到理想的图像,甚至导致系统开发失败。工业镜头相当于人眼的晶状体,如果没有晶状体,人眼看不到任何物体;如果没有镜头,那么摄像头所输出的图像;就是白茫茫的一片,没有清晰的图像输出,这与我们家用摄像机和照相机的原理是一致的。当人眼的肌肉无法将晶状体拉伸至正常位置时,也就是人们常说的近视眼,眼前的景物就变得模糊不清;摄像头与镜头的配合也有类似现象,当图像变得不清楚时,可以调整摄像头的后焦点,改变CCD芯片与工业镜头基准面的距离(相当于调整人眼晶状体的位置),可以将模糊的图像变得清晰。由此可见,镜头在闭路监控系统中的作用是非常重要的。工程设计人员和施工人员都要经常与镜头打交道:设计人员要根据物距、成像大小计算镜头焦距,施工人员经常进行现场调试,其中

  • Spring整合Mybaits java.sql.SQLException: Access denied for user '***'@'localhost' (using password: YES

    最近在搞Spring和Mybatis的整合,当我们在Spring里面配置数据源,而数据源是从外部的properties文件读取过来的时候就会报错java.sql.SQLException:Accessdeniedforuser'Rebirth'@'localhost'(usingpassword:YES)db.propertiesdriver=com.mysql.jdbc.Driver url=jdbc:mysql:///test username=root password=admin复制spring的数据源配置代码<!--加载数据库属性配置文件--> <context:property-placeholderlocation="classpath:db.properties"/> <!--配置数据源--> <beanid="dataSource"class="org.springframework.jdbc.datasource.DriverMana

  • Cloudflare的HTTP/2优化策略

    Cloudflare针对HTTP/2优先级的进一步优化,将网页控制权尽可能地交给网站所有者,可根据具体需求与场景,定制化网页加载优先级策略,提供更快速,更优质的用户Web访问与交互体验。文/PatrickMeenan译/John原文https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/HTTP/2意味着更快的网页加载速度,而Cloudflare在很久之前也为所有客户提供了HTTP/2访问服务。但是其中HTTP/2的一项特性——加载优先级,并没有达到预期的效果。事实上优先级特性本身并没有什么问题,真正地问题在于浏览器中优先级特性的实现方式。现在,Cloudflare推出了对于HTTP/2优先级的优化升级,也就是让我们的服务器有能力控制优先级策略从而真正提高网页的加载速度。在此之前,浏览器已经能够控制并决定加载网页内容的方式与时长。而现在我们希望能通过对优先级模型进行升级,将网页控制权尽可能地交给网站所有者。客户可以在Cloudflare仪表板的“Speed”选项卡中启用“增强HTTP/2优先级”

  • 宜信架构实践|SDN网络IPv6组播机制支持实时视频业务海量用户扩展

    一、背景:随着互联网的迅猛发展,诸如视频直播、网络教学等实时业务的广泛应用,多个接收者需要同时从一个或多个源节点接收相同的流媒体数据,网络传输的信息容量大大增加,占用大量的网络带宽。对这些应用需求,传统的点播技术,不仅对源节点资源和网络带宽的消耗很大,同时用户数量的扩展受到限制。比较而言,组播是一个很好的传输方案。由于传统网络中路由器需要预先配置,然后才可以动态支持组播订阅者的加入、离开操作和组播树的生成操作,并且传统网络中的路由器没有针对用户对带宽的大需求来动态选择传输路径,很容易造成链路拥塞,不能够为用户提供较好的服务质量,难以在传统网络中大规模部署。以OpenFlow技术为核心的软件定义网络(SDN)框架具有集中控制的功能,能够自己感知网络拓扑的变化,在细粒度的路径选择、接入控制、负载均衡方面有着天然的优势,为IPv6组播功能的实现提供了好的解决方案。为了解决SDN网络下的IPv6组播问题,提出了在SDN控制器中设计组成员管理、带宽拓扑维护、组播树的构建三个功能模块,不再需要部署分布式的组播路由协议。二、SDN简介SDN是来源于斯坦福大学的CleanSlate项目组,他们有一个宏

  • 第5章 Spring Boot自动配置原理

    第5章SpringBoot自动配置原理5.1SpringBoot的核心组件模块首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量:我们cd到spring-boot-autoconfigure工程根目录下。执行$tree|grep-c.java$复制模块java文件数spring-boot551spring-boot-actuator423spring-boot-autoconfigure783spring-boot-devtools169spring-boot-cli180spring-boot-tools355我们可以看到有783个java文件。spring-boot核心工程有551个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核心组成部分:spring-boot-autoconfigure spring-boot spring-boot-tools复制我们把SpringBoot源码导入IntelliJIDEA,查看artifact的全部依赖关系。IDEA有个MavenProjects窗口,一般在右侧能够找到,如果没有可以

  • 测试环境的迁移式升级和数据整合(r8笔记第27天)

    很多时候,大家工作中都会有一种被动的思维,那就是能不动就不动,从求稳的角度来看无可厚非,但是从风险的角度来说,还是有待商榷的。如果存在风险,还保持原样很可能就是一个不定时炸弹。 这不手头有一套环境,按照以前的标准是根本入不了我的法眼的,但是因为是测试环境,小问题比较多,存在容灾风险,但是这么多年一直这样,也就默然接受了。 这套环境硬件配置很低,基本上和我的笔记本配置差不多,可能还略差一些,在上面跑着3个数据库实例,其中一个是11g的,2个是10g的。两个10g的数据库实例数据量都不大,几十G而已。 看起来是有些别扭,而且这几个数据库实例都是运行在费归档模式下,对于备份目前是采用了逻辑备份的方式,备份了几个重要的schema数据,每天凌晨开始运行,然后上传到异机上去。 听起来也还是可行的,但是一旦发生硬件问题,恢复就是一个大麻烦。 这部凌晨就收到了报警,然后发现这台服务器不可用了。登录ILO之后,发现系统健康情况为Unknown,已经无法连通了。 然后发现备用电源已经停了,强制手工启动之后,算是勉强撑了4个多小时,然后中午又宕机了,下午三点又宕机一次。 当然这个期间,自己已经开始着实一

  • 面试题-Elasticsearch篇

    Elasticsearch可以实现秒级的搜索,cluster是一种分布式的部署,极易扩展(scale)这样很容易使它处理PB级的数据库容量。最重要的是Elasticsearch是它搜索的结果可以按照分数进行排序,它能提供我们最相关的搜索结果(relevance)。 1、概述 特点 安装方便:没有其他依赖,下载后安装非常方便;只用修改几个参数就可以搭建起来一个集群 JSON:输入/输出格式为JSON,意味着不需要定义Schema,快捷方便 RESTful:基本所有操作(索引、查询、甚至是配置)都可以通过HTTP接口进行 分布式:节点对外表现对等(每个节点都可以用来做入口)加入节点自动负载均衡 多租户:可根据不同的用途分索引,可以同时操作多个索引 支持超大数据:可以扩展到PB级的结构化和非结构化数据海量数据的近实时处理 功能 分布式的搜索引擎 分布式:Elasticsearch自动将海量数据分散到多台服务器上去存储和检索 全文检索 提供模糊搜索等自动度很高的查询方式,并进行相关性排名,高亮等功能 数据分析引擎(分组聚合) 社区网站,最近一周用户登

  • 安装源配置文件“/etc/apt/sources.list”问题

    安装docker过程中使用以下命令设置稳定存储库。 $sudoadd-apt-repository\ "deb[arch=amd64]https://download.docker.com/linux/ubuntu\ $(lsb_release-cs)\ stable"由于其中空格问题导致配置文件出现记录格式有误但本身sources.list该文件是只读模式,使用vim等程序都无法修改后发现在终端输入sudogedit/etc/apt/sources.list可以弹出可修改的窗口在相应的行修改保存后即可复制

  • java虚拟机的内存机制

     我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上。所以,对java的学习,离不开对java虚拟机的学习与了解。下面简单整理下java虚拟机的内存模型,用于备忘,加深理解。 一、java虚拟机的模型   话不多说,先上张内存模型图吧: 百度来的图,大概也描述清楚了我们常用的虚拟机的内存模型了,主要分为两大类:线程共享(相当于所有线程都可以访问,如果是单线程程序则对应所有方法都能访问)和线程私有(属于某个线程的数据域),其实我们刚刚接触java的时候,会笼统地将内存分为堆内存和栈内存,前者对应的便是线程共享区,后者对应的便是线程私有区。 二、各个区域存放的数据   1、方法区:存放静态变量、类相关信息(可以理解为class对象的数据和相关方法字节码等)以及字符串等常量。方法区中有一个常量池,它专门存放常用的常量,包括常见的字符串常量。总而言之,这个区域存放的是和类相关的数据。   2、堆:存放各种方法(包括new操作符,反射,clone,反序列等)创建的对象的数据,和方法区相比较:它是存放对象相关的数据

  • Linux DMA Engine framework(3)_dma controller驱动

    http://www.wowotech.net/linux_kenrel/dma_controller_driver.html

  • Ubuntu系统挂载新硬盘的方法

    Ubuntu系统挂载新硬盘的方法  https://www.cnblogs.com/zhongzhaoxie/p/13064442.html

  • Spring学习笔记之JdbcTemplate

    目录1、JdbcTemplate简介2、怎么配置JdbcTemplate3、怎么使用JdbcTemplate1)更新update不具名参数具名参数batchUpdate不具名参数具名参数2)查找不具名参数返回一个对象返回一个列表返回一个特殊的值具名参数 1、JdbcTemplate简介 Spring的官方介绍里开头如是说道 ThisisthecentralclassintheJDBCcorepackage.ItsimplifiestheuseofJDBCandhelpstoavoidcommonerrors. 这是jdbc核心包的核心类,它简化了jdbc的使用并帮助人们避免一些一般的错误 2、怎么配置JdbcTemplate 首先,我们需要配置一个数据源 确定你要使用的数据库连接池 在applicationContext.xml配置文件里配置数据库连接池,即数据源 这里我将使用c3p0连接池 <!--配置数据源--> <beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataS

  • POJ 1845乘法逆元+约数和

    乘法逆元计算等比数列的求和公式 题意    给两个正整数A和B,计算AB的所有因子和的值对9901取模 思路   约数和公式   S=(1+p1+p1^2+.....+p1^k1)*(1+p2+p2^2+.....+p2^k2)*......*(1+pn+pn^2+pn^3+.....+pn^kn);     等比数列公式:(PB+c+1-1)/(p1-1)   当模数mod为质数时,bmod-2逆元即为b的乘法逆元     当p-1不为mod的倍数时,逆元无效,此时p%mod==1,所以分母即为1+12+.....+1B+c #include<iostream> #include<cstdio> usingnamespacestd; typedeflonglongll; constintmaxn=2e5+10; intm; intp[100],c[100]; voiddivide(lln) { m=0; for(inti=2;i*i<=n;++i){ if(n%i==0){ p[++m]=i; while(n%i==0){ n/=i; c[m]++;

  • Shell学习笔记二

    一、调试脚本 调试功能是每一种编程语言都应该实现的重要特性之一,当出现一些始料未及的情况时,用它来生成脚本运行信息。调试信息可以帮你弄清楚是什么原因使得程序发生崩溃或行为异常。每位系统程序员都应该了解Bash提供的调试选项。 shell脚本调试不需要什么特殊的工具。bash自带了一些调试选项。具体选项包含:-x:在执行时显示参数和命令;+x:禁止调试-v:当命令行进行读取时显示输入;+v:禁止打印输入。在shell脚本启动时或者在脚本内都可以添加这些调试选项。测试脚本debug.sh,代码如下所示。 #!/bin/bash foriin{1..6}; do echo$i done echo"Scriptexecuted" 复制    直接运行脚本:./debug.sh。结果如图:   在脚本启动时添加调试选项。来调试debug.sh,可以在启动脚本时,输入以下命令:bash-x./debug.sh或者sh-x./debug.sh。结果如图:   在脚本内添加调试选项,使用set命令。例如:要开启-x选项,则在脚本内容中添加命令

相关推荐

推荐阅读