Ambari集成Apache Kyuubi实践

目前还有很多公司基于HDP来构建自己的大数据平台,随着Apache Kyuubi的持续热度,如何基于原有的HDP产品来集成Apache Kyuubi,很多人都迫切的需求。集成Apache Kyuubi到HDP中,主要涉及Ambari的二次开发。本文详细叙述了集成Apache Kyuubi的实践过程。

1、集成版本信息

服务版本
九尾1.4.1-孵化
安巴里2.7.3
高清图3.1.0
操作系统CentOS 7.4.1708

背景:基于HDP 3.1.0版本,我司完成了Apache版本的所有组件替换,然后集成了Apache Kyuubi。

集成Apache的主要组件版本信息如下

服务版本
高清文件系统3.3.0
3.3.0
MapReduce23.3.0
蜂巢3.1.2
火花3.1.1

2、集成步骤

自定义组件添加分为两大部分,一部分是需要将组件的可文件打包成RPM,另一部分是在Ambari 中添加组件的配置信息,启动脚本等。

2.1 制作RPM包

使用Ambari 安装或集成大数据组件时,需要将组件格式制作成 rpm 格式。

2.1.1 下载并解压Apache Kyuubi

下载地址:https://kyuubi.apache.org/releases.html

在本次集成中我们选择的是1.4.1-incubating版本。

执行tar zxf apache-kyuubi-1.4.1-incubating-bin.tgz,Kyuubi安装包结构简介

apache-kyuubi-1.4.1-incubating-bin├── DISCLAIMER├── LICENSE├── NOTICE├── RELEASE├── beeline-jars├── bin├── conf|   ├── kyuubi-defaults.conf.template│   ├── kyuubi-env.sh.template│   └── log4j2.properties.template├── docker│   ├── Dockerfile│   ├── helm│   ├── kyuubi-configmap.yaml│   ├── kyuubi-deployment.yaml│   ├── kyuubi-pod.yaml│   └── kyuubi-service.yaml├── externals│  └── engines├── jars├── licenses├── logs├── pid└── work

2.1.2 创建RPM包制作环境

安装 rpm-build 包

yum install rpm-build

安装 rpmdevtools

yum install rpmdevtools

创建工作空间

rpmdev-setuptree

安装工作空间简介

图片

2.1.3 制作RPM包

2.1.3.1 编辑Spec文件

制作rpm包需要用spec格式的文件。根据Kyuubi解压后的目录结构,需要自行编辑spec文件以包含所有需要的目录及文件。部分截图概要

%descriptionkyuubi%files%dir %attr(0755, root, root) "/usr/hdp/3.1.0.0-78/kyuubi"%attr(0644, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/DISCLAIMER"%attr(0644, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/LICENSE"%attr(0644, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/NOTICE"%attr(0644, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/RELEASE"%dir %attr(0777, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/beeline-jars"%dir %attr(0777, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/logs"%dir %attr(0777, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/pid"%dir %attr(0777, root, root) "/usr/hdp/3.1.0.0-78/kyuubi/work"
%changelog

2.1.3.2 更换文件

创建目录

cd /root/rpmbuild/BUILDROOTmkdir -p /root/rpmbuild/BUILDROOT/kyuubi_3_1_0_0_78-2.3.2.3.1.0.0-78.x86_64/usr/hdp/3.1.0.0-78/kyuubi

转到apache-kyuubi-1.4.1-incubating-bin.tgz解压后目录

cp -r * /root/rpmbuild/BUILDROOT/kyuubi_3_1_0_0_78-2.3.2.3.1.0.0-78.x86_64/usr/hdp/3.1.0.0-78/kyuubi

将kyuubi.spec文件放到/root/rpmbuild/SPECS文件夹中

cp kyuubi.spec /root/rpmbuild/SPECS/

2.1.3.3 执行打包。

cd /root/rpmbuild/SPECSrpmbuild -ba kyuubi.spec

查看 rpm 包

打包好的rpm包在/root/rpmbuild/RPMS虚拟机

图片

2.1.4更新YUM源

将上步骤中生成rpm的目标yum源中对应目录,保持完成后执行更新操作

createrepo --update ./

2.2 Ambari集成Apache Kyuubi

2.2.1 公民服务目录结构

在Ambari中添加自定义服务,需要配置文件以Spark详细说明

图片

配置

该目录下存放的是spark的属性配置文件,对应Ambari页面的属性配置页面,可以设置默认值,类型,描述等信息。

包/脚本

该目录下存放服务操作相关的脚本,如服务启动,服务停止,服务检查等。

包/模板

该目录可存放,存放的是组件属性的配置信息,和配置目录下的配置对应,这个关系是如果我们在Ambari页面修改了属性信息,则修改信息会自动填充该目录下的文件的属性,所以,这个目录下的属性是最新的,并且是服务要调用

包裹/警报

该程序存放告急配置,例如程序断网、运行时告急

快速链接

该目录下存放的是快速链接配置,Ambari页面通过该配置可以跳转到我们想要跳转的页面。

指标.json

用来配置指标相关配置

kerberos.json

用来配置kerberos认证

元信息文件

这个文件很重要,主要是配置服务名称、服务类型、服务操作脚本、服务组件、指标以及快速链接等信息。

2.2.2 添加Kyuubi组件

在司的应用场景中,主要是用Kyuubi来替换Spark Thrift Server,依赖于Spark服务中集成Kyuubi组件。实现如下图所示的效果

图片

2.2.2.1 编辑metainfo.xml

在ambari-server/src/main/resources/stacks/HDP/3.0/services/SPARK目录中首先编辑metainfo.xml,为spark服务添加Kyuubi组件

<component>  <name>KYUUBI_SEVER</name>  <displayName>KYUUBI SEVER</displayName>  <category>SLAVE</category>  <cardinality>0+</cardinality>  <versionAdvertised>true</versionAdvertised>  <dependencies>    <dependency>      <name>HDFS/HDFS_CLIENT</name>      <scope>host</scope>      <auto-deploy>        <enabled>true</enabled>      </auto-deploy>    </dependency>    <dependency>      <name>MAPREDUCE2/MAPREDUCE2_CLIENT</name>      <scope>host</scope>      <auto-deploy>        <enabled>true</enabled>      </auto-deploy>    </dependency>    <dependency>      <name>YARN/YARN_CLIENT</name>      <scope>host</scope>      <auto-deploy>        <enabled>true</enabled>      </auto-deploy>    </dependency>    <dependency>      <name>SPARK/SPARK_CLIENT</name>      <scope>host</scope>      <auto-deploy>        <enabled>true</enabled>      </auto-deploy>    </dependency>    <dependency>      <name>HIVE/HIVE_METASTORE</name>      <scope>cluster</scope>      <auto-deploy>        <enabled>true</enabled>      </auto-deploy>    </dependency>  </dependencies>  <commandScript>    <script>scripts/kyuubi_server.py</script>    <scriptType>PYTHON</scriptType>    <timeout>600</timeout>   </commandScript>  <logs>    <log>      <logId>kyuubi_server</logId>      <primary>true</primary>    </log>  </logs></component>

其中kyuubi_server.py定义了安装、配置、启动、停止、获取服务状态等功能。

<configuration-dependencies>  <config-type>core-site</config-type>  <config-type>spark-defaults</config-type>  <config-type>spark-env</config-type>  <config-type>spark-log4j-properties</config-type>  <config-type>spark-metrics-properties</config-type>  <config-type>spark-thrift-sparkconf</config-type>  <config-type>spark-hive-site-override</config-type>  <config-type>spark-thrift-fairscheduler</config-type>  <config-type>kyuubi-defaults</config-type>  <config-type>kyuubi-env</config-type>  <config-type>kyuubi-log4j-properties</config-type>  <config-type>ranger-spark-audit</config-type>  <config-type>ranger-spark-security</config-type></configuration-dependencies>

configuration-dependencies ></ configuration-dependencies >标签内添加kyuubi相关配置项,包括kyuubi-defaults、kyuubi-env、kyuubi-log4j-properties、ranger-spark-audit、ranger-spark-security。

<osSpecific>  <osFamily>redhat7,amazonlinux2,redhat6,suse11,suse12</osFamily>  <packages>    <package>      <name>spark2_${stack_version}</name>    </package>    <package>      <name>spark2_${stack_version}-python</name>    </package>    <package>      <name>kyuubi_${stack_version}</name>    </package>  </packages></osSpecific>

package </ package >标签内添加kyuubi rpm包名称信息

2.2.2.2 编辑kyuubi_server.py文件

#!/usr/bin/env pythonimport osfrom resource_management import *
class KyuubiServer(Script):    def install(self, env):        self.install_packages(env)
    def configure(self, env, upgrade_type=None, config_dir=None):        import kyuubi_params        env.set_params(kyuubi_params)
        Directory([kyuubi_params.kyuubi_log_dir, kyuubi_params.kyuubi_pid_dir, kyuubi_params.kyuubi_metrics_dir, kyuubi_params.kyuubi_operation_log_dir],                  owner=kyuubi_params.kyuubi_user,                  group=kyuubi_params.kyuubi_group,                  mode=0775,                  create_parents = True                  )
        kyuubi_defaults = dict(kyuubi_params.config['configurations']['kyuubi-defaults'])
        PropertiesFile(format("{kyuubi_conf_dir}/kyuubi-defaults.conf"),               properties = kyuubi_defaults,               key_value_delimiter = " ",               owner=kyuubi_params.kyuubi_user,               group=kyuubi_params.kyuubi_group,               mode=0644               )
        # create kyuubi-env.sh in kyuubi install dir        File(os.path.join(kyuubi_params.kyuubi_conf_dir, 'kyuubi-env.sh'),             owner=kyuubi_params.kyuubi_user,             group=kyuubi_params.kyuubi_group,             content=InlineTemplate(kyuubi_params.kyuubi_env_sh),             mode=0644,        )
        #create log4j.properties kyuubi install dir        File(os.path.join(kyuubi_params.kyuubi_conf_dir, 'log4j.properties'),             owner=kyuubi_params.kyuubi_user,             group=kyuubi_params.kyuubi_group,             content=kyuubi_params.kyuubi_log4j_properties,             mode=0644,        )
    def start(self, env, upgrade_type=None):        import kyuubi_params        env.set_params(kyuubi_params)
        self.configure(env)        Execute(kyuubi_params.kyuubi_start_cmd,user=kyuubi_params.kyuubi_user,environment={'JAVA_HOME': kyuubi_params.java_home})
    def stop(self, env, upgrade_type=None):        import kyuubi_params        env.set_params(kyuubi_params)        self.configure(env)
        Execute(kyuubi_params.kyuubi_stop_cmd,user=kyuubi_params.kyuubi_user,environment={'JAVA_HOME': kyuubi_params.java_home})
    def status(self, env):        import kyuubi_params        env.set_params(kyuubi_params)        check_process_status(kyuubi_params.kyuubi_pid_file)
    def get_user(self):        import kyuubi_params        return kyuubi_params.kyuubi_user
    def get_pid_files(self):        import kyuubi_params        return [kyuubi_params.kyuubi_pid_file]
if __name__ == "__main__":    KyuubiServer().execute()

kyuubi_server.py定义了安装、配置、启动、停止Kyuubi服务的逻辑。

kyuubi_params配置变量以及需要的相关参数,由于篇幅原因这里不推荐使用。

2.2.2.3 编辑kyuubi_default.xml文件

<?xml version="1.0" encoding="UTF-8"?><configuration supports_final="true">    <property>        <name>kyuubi.ha.zookeeper.quorum</name>        <value>{{cluster_zookeeper_quorum}}</value>        <description>            The connection string for the zookeeper ensemble        </description>        <on-ambari-upgrade add="true"/>    </property>
    <property>        <name>kyuubi.frontend.thrift.binary.bind.port</name>        <value>10009</value>        <description>            Port of the machine on which to run the thrift frontend service via binary protocol.        </description>        <on-ambari-upgrade add="true"/>    </property>
    <property>        <name>kyuubi.ha.zookeeper.session.timeout</name>        <value>600000</value>        <description>            The timeout(ms) of a connected session to be idled        </description>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>kyuubi.session.engine.initialize.timeout</name>        <value>300000</value>        <description>            Timeout for starting the background engine, e.g. SparkSQLEngine.        </description>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>kyuubi.authentication</name>        <value>{{kyuubi_authentication}}</value>        <description>            Client authentication types        </description>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>spark.master</name>        <value>yarn</value>        <description>            The deploying mode of spark application.        </description>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>spark.submit.deployMode</name>        <value>cluster</value>        <description>spark submit deploy mode</description>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>spark.yarn.queue</name>        <value>default</value>        <description>            The name of the YARN queue to which the application is submitted.        </description>        <depends-on>            <property>                <type>capacity-scheduler</type>                <name>yarn.scheduler.capacity.root.queues</name>            </property>        </depends-on>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>spark.yarn.driver.memory</name>        <value>4g</value>        <description>spark yarn driver momory</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>spark.executor.memory</name>        <value>4g</value>        <description>spark.executor.memory</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>spark.sql.extensions</name>        <value>org.apache.submarine.spark.security.api.RangerSparkSQLExtension</value>        <description>spark sql ranger extension</description>        <on-ambari-upgrade add="false"/>    </property></configuration>

其中kyuubi.ha.zookeeper.quorum属性配置的值值为{{cluster_zookeeper_quorum}},会在kyuubi安装中自动替换为当前zk集群的信息。

kyuubi.authentication属性配置的值值为{{kyuubi_authentication}},在kyuubi安装中判断当前集群是否开启kerberos认证,来设置true或者false。

2.2.2.4 编辑kyuubi_env.xml文件

<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration supports_adding_forbidden="true">    <property>        <name>kyuubi_user</name>        <display-name>Kyuubi User</display-name>        <value>spark</value>        <property-type>USER</property-type>        <value-attributes>            <type>user</type>            <overridable>false</overridable>            <user-groups>                <property>                    <type>cluster-env</type>                    <name>user_group</name>                </property>                <property>                    <type>kyuubi-env</type>                    <name>kyuubi_group</name>                </property>            </user-groups>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>kyuubi_group</name>        <display-name>Kyuubi Group</display-name>        <value>spark</value>        <property-type>GROUP</property-type>        <description>kyuubi group</description>        <value-attributes>            <type>user</type>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>kyuubi_log_dir</name>        <display-name>Kyuubi Log directory</display-name>        <value>/var/log/kyuubi</value>        <description>Kyuubi Log Dir</description>        <value-attributes>            <type>directory</type>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property>    <property>        <name>kyuubi_pid_dir</name>        <display-name>Kyuubi PID directory</display-name>        <value>/var/run/kyuubi</value>        <value-attributes>            <type>directory</type>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property>
    <!-- kyuubi-env.sh -->    <property>        <name>content</name>        <description>This is the jinja template for kyuubi-env.sh file</description>        <value>#!/usr/bin/env bash
export JAVA_HOME={{java_home}}export HADOOP_CONF_DIR=/etc/hadoop/confexport SPARK_HOME=/usr/hdp/current/spark-clientexport SPARK_CONF_DIR=/etc/spark/confexport KYUUBI_LOG_DIR={{kyuubi_log_dir}}export KYUUBI_PID_DIR={{kyuubi_pid_dir}}        </value>        <value-attributes>            <type>content</type>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property></configuration>

本文件主要设置JAVA_HOME、HADOOP_CONF_DIR、KYUUBI_LOG_DIR、KYUUBI_PID_DIR等相关路径信息

2.2.2.5 编辑kyuubi-log4j-properties.xml文件

<?xml version="1.0" encoding="UTF-8"?><configuration supports_final="false" supports_adding_forbidden="true">    <property>        <name>content</name>        <description>Kyuubi-log4j-Properties</description>        <value># Set everything to be logged to the consolelog4j.rootCategory=INFO, consolelog4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.target=System.errlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %p %c{2}: %m%n
# Set the default kyuubi-ctl log level to WARN. When running the kyuubi-ctl, the# log level for this class is used to overwrite the root logger's log level.log4j.logger.org.apache.kyuubi.ctl.ServiceControlCli=ERROR        </value>        <value-attributes>            <type>content</type>            <show-property-name>false</show-property-name>        </value-attributes>        <on-ambari-upgrade add="true"/>    </property></configuration>

2.2.2.6 编辑ranger-spark-security.xml文件

<?xml version="1.0"?><configuration>    <property>        <name>ranger.plugin.spark.service.name</name>        <value>{{repo_name}}</value>        <description>Name of the Ranger service containing policies for this SPARK instance</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>ranger.plugin.spark.policy.source.impl</name>        <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>        <description>Class to retrieve policies from the source</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>ranger.plugin.spark.policy.rest.url</name>        <value>{{policymgr_mgr_url}}</value>        <description>URL to Ranger Admin</description>        <on-ambari-upgrade add="false"/>        <depends-on>            <property>                <type>admin-properties</type>                <name>policymgr_external_url</name>            </property>        </depends-on>    </property>    <property>        <name>ranger.plugin.spark.policy.pollIntervalMs</name>        <value>30000</value>        <description>How often to poll for changes in policies?</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>ranger.plugin.spark.policy.cache.dir</name>        <value>/etc/ranger/{{repo_name}}/policycache</value>        <description>Directory where Ranger policies are cached after successful retrieval from the source</description>        <on-ambari-upgrade add="false"/>    </property></configuration>

本文件主要用来配置spark ranger相关参数。

2.2.2.7 编辑ranger-spark-audit.xml文件

<?xml version="1.0"?><configuration>    <property>        <name>xasecure.audit.is.enabled</name>        <value>true</value>        <description>Is Audit enabled?</description>        <value-attributes>            <type>boolean</type>        </value-attributes>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>xasecure.audit.destination.db</name>        <value>false</value>        <display-name>Audit to DB</display-name>        <description>Is Audit to DB enabled?</description>        <value-attributes>            <type>boolean</type>        </value-attributes>        <depends-on>            <property>                <type>ranger-env</type>                <name>xasecure.audit.destination.db</name>            </property>        </depends-on>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>xasecure.audit.destination.db.jdbc.driver</name>        <value>{{jdbc_driver}}</value>        <description>Audit DB JDBC Driver</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>xasecure.audit.destination.db.jdbc.url</name>        <value>{{audit_jdbc_url}}</value>        <description>Audit DB JDBC URL</description>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>xasecure.audit.destination.db.password</name>        <value>{{xa_audit_db_password}}</value>        <property-type>PASSWORD</property-type>        <description>Audit DB JDBC Password</description>        <value-attributes>            <type>password</type>        </value-attributes>        <on-ambari-upgrade add="false"/>    </property>    <property>        <name>xasecure.audit.destination.db.user</name>        <value>{{xa_audit_db_user}}</value>        <description>Audit DB JDBC User</description>        <on-ambari-upgrade add="false"/>    </property></configuration>

本文件主要用来配置spark ranger audit 相关参数。

2.2.2.8 编辑alerts.json文件

"KYUUBI_SEVER": [  {    "name": "kyuubi_server_status",    "label": "Kyuubi Server",    "description": "This host-level alert is triggered if the Kyuubi Server cannot be determined to be up.",    "interval": 1,    "scope": "ANY",    "source": {      "type": "SCRIPT",      "path": "DIF/3.0/services/SPARK/package/scripts/alerts/alert_kyuubi_server_port.py",      "parameters": [        {          "name": "check.command.timeout",          "display_name": "Command Timeout",          "value": 120.0,          "type": "NUMERIC",          "description": "The maximum time before check command will be killed by timeout",          "units": "seconds",          "threshold": "CRITICAL"        }      ]    }  }]

在alert.json文件中添加检测kyuubi服务器是否启动的告警检测配置,每隔120秒检测一次kyuubi服务器服务是否正常。检测逻辑由alert_kyuubi_server_port.py实现

2.2.2.9 编辑alert_kyuubi_server_port.py文件

alert_kyuubi_server_port.py的实现逻辑可以参考alert_spark_thrift_port.py,在此不具体实现逻辑,原理就是定时执行beeline连接操作判断网站上的连接成功。

2.2.2.10 编辑kerberos.json文件

{  "name": "kyuubi_service_keytab",  "principal": {    "value": "spark/_HOST@${realm}",    "type" : "service",    "configuration": "kyuubi-defaults/kyuubi.kinit.principal",    "local_username" : "${spark-env/spark_user}"  },  "keytab": {    "file": "${keytab_dir}/spark.service.keytab",    "owner": {      "name": "${spark-env/spark_user}",      "access": "r"    },    "group": {      "name": "${cluster-env/user_group}",      "access": ""    },    "configuration": "kyuubi-defaults/kyuubi.kinit.keytab"  }}

在kerberos.json文件中添加自动生成principal、keytab配置到kyuubi-defaults的逻辑。在集群启动kerberos认证的时候,会自动在kyuubi-defaults中添加kyuubi.kinit.keytab及kyuubi.kinit.principal配置项。

2.2.2.11 更新 ambari-server、ambari-agent RPM

将上述修改以及添加的文件内容更新到ambari-server、ambari-agent RPM包中的相应目录中。

对于已经安装的套件,可以通过如下操作进行:

1.卸载spark服务

2.将上述添加的文件放到如下目录的位置:

/var/lib/ambari-server/resources/stacks/HDP/3.0/services/SPARK/var/lib/ambari-agent/cache/stacks/DIF/3.0/services/SPARK

3. 在ambari-serer执行sudo ambari-server restart

4. 在ambari-agent所在节点执行sudo ambari-agent restart

5. 重新安装spark服务

3、效果展示

3.1 安装效果展示

安装spark时,支持选择kyuubi服务器组件

图片

安装过程中可以在界面上配置kyuubi参数

图片

3.2 安装成功后效果展示

安装成功

图片

Kyuubi相关配置页面展示成功

图片

图片

3.3 停掉Kyuubi Server效果展示

界面上停止掉kyuubi服务器

图片

界面展示停止成功

图片

界面告警提示kyuubi server停止

图片

重新启动服务器

图片

说警消失

图片

使用ambari-qa用户在后台通过beeline连接,可以连接成功

图片

在yarn界面上看到用户ambari-qa应用程序运行成功

图片

引用文献:

Ambari集成Apache Kyuubi实践

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享一个用python的本地WIFI密码查看器

本章教程&#xff0c;主要分享一个本地wifi密码查看器&#xff0c;用python实现的&#xff0c;感兴趣的可以试一试。 具体代码 import subprocess # 导入 subprocess 模块&#xff0c;用于执行系统命令 import tkinter as tk # 导入 tkinter 模块&#xff0c;用于创建图形用…

实现Ingress-Nginx Controller高可用方案

文章目录 前提准备1.修改Ingress-Controller 运行模式为hostNetwork并生效2.给部署ingress-controller的节点打标签3.查看ingress-controller的部署情况 方式一&#xff1a;LVSKeepalivedNginxIngress一、部署ipvsadm和keepalived二、配置keepalived1.配置lvs01(keepalived mas…

Java Web学习笔记27——对话框、表单组件

常见组件对话框&#xff1a; Dialog对话框&#xff1a;在保留当前页面状态下&#xff0c;告知用户并承载相关操作。 dialogTableVisible: false 默认是不可见的。 在按钮属性中设置为true的意思&#xff0c;点击按钮的时候&#xff0c;才会true&#xff0c;对话框才会显示。 …

python Tk 获取输入框内容,分割内容

创建输入框、一个按钮和一个标签的GUI。 用户可以在输入框中输入文本&#xff0c;点击按钮后&#xff0c;程序将在控制台打印输入的文本&#xff08;已经分割为列表&#xff09;&#xff0c;并在GUI中的标签上显示一些静态文本。 import tkinter as tk# 创建主窗口 root tk.…

基于SpringBoot+Vue学生请假管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

linux指令--sed

sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 语法解析 sed [选项] 编辑命令 文件 选项&#xff1a; -n&#xff1a;只显示匹配处理的行-e&#xff1a;执行多个编辑命令时-i&#xff1a;在原文件中进行修改&#xff0c;不输出到屏幕-…

qsort函数

学习c语言的过程中少不了的就是排序&#xff0c;例如冒泡排序&#xff08;不清楚的同学可以翻找一下之前的文章&#xff09;&#xff0c; 我们这里将冒泡排序作为一个自定义函数来呈现一下 #include<stdio.h>void bubble_sort(int arr[], int len) {for (int i 0; i &…

【Vue】mutations

文章目录 一、定义mutations二、组件中提交 mutations三、带参数的 mutations 一、定义mutations mutations是vuex中的对象&#xff0c;这个对象可以定义在当前store的配置项中 const store new Vuex.Store({state: {count: 0},// 定义mutations// mutations是一个对象&#x…

Progressive Feature Fusion Framework Based on Graph Convolutional Network

以Resnet50作为主干网络&#xff0c;然后使用GCN逐层聚合多级特征&#xff0c;逐级聚合这种模型架构早已不新鲜&#xff0c;这篇文章使用GCN的方式对特征进行聚合&#xff0c;没有代码。这篇文章没有过多的介绍如何构造的节点特征和邻接矩阵&#xff0c;我觉得对于图卷积来说&a…

自动化Reddit图片收集:Python爬虫技巧

引言 Reddit&#xff0c;作为一个全球性的社交平台&#xff0c;拥有海量的用户生成内容&#xff0c;其中包括大量的图片资源。对于数据科学家、市场研究人员或任何需要大量图片资源的人来说&#xff0c;自动化地从Reddit收集图片是一个极具价值的技能。本文将详细介绍如何使用…

多个p标签一行展示,溢出隐藏

一开始&#xff0c;我是让div包裹多个p标签&#xff0c;并让div“flex”布局&#xff0c;且单行溢出隐藏&#xff0c;可是发现当父元素或当前元素有flex时&#xff0c;text-overflow: ellipsis;是不生效的 大多数解决办法都是&#xff0c;不要flex&#xff0c;或者给div下的每个…

【启程Golang之旅】网络编程与反射

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

Java进阶_多态特性

生活中的多态 多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作&#xff0c;如图所示&#xff1a; 现实中&#xff0c;比如我们按下 F1 键这个动作&#xff0c;同一个事件发生在不同的对象上会产生不同的结果。…

达梦8 探寻达梦排序机制之一:传统排序机制(SORT_FLAG=0)

测试版本&#xff1a;--03134283938-20221019-172201-20018 达梦的排序机制由四个dm.ini参数控制&#xff1a; SORT_BUF_SIZE 100 #maximum sort buffer size in MegabytesSORT_BLK_SIZE 1 #ma…

自动化立体库集成技术--含(思维导图)

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 随着科技的不断进步和物流行业的快速发展&#xff0c;自动化立体库集成技术已成为现代物流仓储的重要支撑。 它利用先进的自动化设备和智能化管理…

[leetcode hot 150]第一百三十七题,只出现一次的数字Ⅱ

题目&#xff1a; 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 由于需要常数级空间和线性时间复杂度…

http协议,tomcat的作用

HTTP 概念:Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。 特点: 1.基于TCP协议:面向连接&#xff0c;安全 2. 基于请求-响应模型的:一次请求对应一次响应 3HTTP协议是无状态的协议:对于事务处理没有记忆能…

tsconfig.json和tsconfig.app.json文件解析(vue3+ts+vite)

tsconfig.json {"files": [],"references": [{"path": "./tsconfig.node.json"},{"path": "./tsconfig.app.json"}] }https://www.typescriptlang.org/tsconfig/#files files: 在这个例子中&#xff0c;files 数…

git-生成SSH密钥

git-生成SSH密钥 1 打开命令窗口2 操作 1 打开命令窗口 选择"Git Bash Here"&#xff0c;打开Git命令窗口 2 操作 查看当前用户名称 git config user.name配置你的邮箱&#xff0c;“6xxxqq.com” 填写自己的邮箱 git config --global user.email "6xxxqq…

认识Java中的String类

前言 大家好呀&#xff0c;本期将要带大家认识一下Java中的String类&#xff0c;本期注意带大家认识一些String类常用方法&#xff0c;和区分StringBuffer和StringBuilder感谢大家收看 一&#xff0c;String对象构造方法与原理 String类为我们提供了非常多的重载的构造方法让…