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.rhkb.cn/news/344275.html

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

相关文章

Duilib多标签选项卡拖拽效果:添加动画特效!

动画是小型界面库的“难题”、“通病” 几年前就有人分享了如何用direct UI制作多标签选项卡界面的方法。还有人出了一个简易的浏览器demo。但是他们的标签栏都没有Chrome浏览器那样的动画特效。 如何给界面添加布局是的动画特效呢&#xff1f; 动画使界面看起来高大上&#…

HQL面试题练习 —— 求连续段的最后一个数及每个连续段的个数

目录 1 题目2 建表语句3 题解 题目来源&#xff1a;拼多多。 1 题目 有一张表t_id记录了id&#xff0c;id不重复&#xff0c;但是会存在间断&#xff0c;求出连续段的最后一个数及每个连续段的个数。 ----- | id | ----- | 1 | | 2 | | 3 | | 5 | | 6 | | 8 | | …

2024 年最新 Python 基于百度智能云实现文字识别 OCR 详细教程

文字识别 OCR 概述 文字识别OCR&#xff08;Optical Character Recognition&#xff09;提供多场景、多语种、高精度的文字检测与识别服务&#xff0c;多项ICDAR指标居世界第一。广泛适用于金融服务、财税报销、法律政务、保险医疗、快递物流、交通出行、教育培训等场景&#…

设计模式-外观(门面)模式(结构型)

外观模式 外观模式又称门面模式&#xff08;结构型模式&#xff09;&#xff0c;它是一个可以屏蔽系统复杂性的设计模式。俗话说没有什么问题是加一层“介质”解决不了的&#xff0c;如果有那就在加一层。在开发过程中肯定封装过Utils类&#xff0c;我认为这就是一种门面模式&…

RocketMQ的安装

首先到RocketMQ官网下载页面下载 | RocketMQ (apache.org)&#xff0c;本机解压缩&#xff0c;作者在这里用的是最新的5.2.0版本。按照如下步骤安装。 1、环境变量配置rocket mq地址 ROCKETMQ_HOME D:\rocketmq-all-5.2.0-bin-release 在变量path中添加”%ROCKETMQ_HOME%\bi…

Python | Leetcode Python题解之第132题分割回文串II

题目&#xff1a; 题解&#xff1a; class Solution:def minCut(self, s: str) -> int:n len(s)g [[True] * n for _ in range(n)]for i in range(n - 1, -1, -1):for j in range(i 1, n):g[i][j] (s[i] s[j]) and g[i 1][j - 1]f [float("inf")] * nfor …

Block Transformer:通过全局到局部的语言建模加速LLM推理

在基于transformer的自回归语言模型&#xff08;LMs&#xff09;中&#xff0c;生成令牌的成本很高&#xff0c;这是因为自注意力机制需要关注所有之前的令牌&#xff0c;通常通过在自回归解码过程中缓存所有令牌的键值&#xff08;KV&#xff09;状态来解决这个问题。但是&…

英码科技推出鸿蒙边缘计算盒子:提升国产化水平,增强AI应用效能,保障数据安全

当前&#xff0c;随着国产化替代趋势的加强&#xff0c;鸿蒙系统Harmony OS也日趋成熟和完善&#xff0c;各行各业都在积极拥抱鸿蒙&#xff1b;那么&#xff0c;边缘计算要加快实现全面国产化&#xff0c;基于鸿蒙系统开发AI应用势在必行。 关于鸿蒙系统及其优势 鸿蒙系统是华…

SpringCloud-面试篇(二十三)

&#xff08;1&#xff09;SpringCloud常见组件有那些 有无数微服务需要相互调用&#xff1a;可以用远程调用组件OpenFeign组件&#xff0c;也可以用Dobble 这么多微服务相互调用怎么管理&#xff1a;就用到注册中心组件Nacos&#xff0c;Eureka 所有的服务去找注册中心做注…

计算机组成结构—IO方式

目录 一、程序查询方式 1. 程序查询基本流程 2. 接口电路 3. 接口工作过程 二、程序中断方式 1. 程序中断基本流程 2. 接口电路 3. I/O 中断处理过程 三、DMA 方式 1. DMA 的概念和特点 2. DMA 与 CPU 的访存冲突 3. DMA 接口的功能 4. DMA 接口的组成 5. DMA 的…

先求生存,再谋发展:俞敏洪的创业哲学与产品创新之路

引言&#xff1a; 在创业的道路上&#xff0c;每一个创业者都面临着无数的挑战和选择。俞敏洪&#xff0c;新东方教育科技集团的创始人&#xff0c;以其独特的创业哲学和坚韧不拔的精神&#xff0c;带领新东方从一个小小的培训机构成长为全球知名的教育品牌。他的成功经验告诉…

AndroidStudio无法识别连接夜神模拟器

方法一(无法从根本上解决) ①进入夜神模拟器安装路径下的bin路径(安装路径可以带有中文路径) ②打开cmd窗口,输入以下代码(一定要打开模拟器) nox_adb.exe connect 127.0.0.1:62001 方法二(根本上解决) 原因:Android Studio的adb版本与夜神模拟器的adb版本不一致 ①打开And…

突发!凌晨4点某制造业大厂国产数据库集群故障...

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、My…

【C/C++】IO流

目录 前言&#xff1a; 一&#xff0c;C语言的I/O流 二&#xff0c;C的I/O流 2-1&#xff0c;C标准IO流 2-2&#xff0c;IO流的连续输入 前言&#xff1a; “流”即是流动的意思&#xff0c;是物质从一处向另一处流动的过程&#xff0c;是对一种有序连续且具有方向性的数据…

新品发布 | 飞凌嵌入式RK3576核心板,为AIoT应用赋能

为了充分满足AIoT市场对高性能、高算力和低功耗主控日益增长的需求&#xff0c;飞凌嵌入式全新推出基于Rockchip RK3576处理器开发设计的FET3576-C核心板&#xff01; 集成4个ARM Cortex-A72和4个ARM Cortex-A53高性能核&#xff0c;内置6TOPS超强算力NPU&#xff0c;为您的AI…

【RK3568】制作Android11开机动画

Android 开机 logo 分为两种&#xff1a;静态显示和动态显示。静态显示就是循环显示一张图片&#xff1b;动态显示就是以特定帧率顺序显示多张图片 1.准备 android logo 图片 Android logo最好是png格式的&#xff0c;因为同一张图片的情况下&#xff0c;png 格式的比 jpg和b…

海思SS928(SD3403)部署YOLOv5-YOLOv7步骤详解

1. YOLO模型资料 本文档内容以yolov5-7.0工程、yolov5s模型为例。 a. 模型结构 详细的模型结构可以利用netron工具打开.pt或.onnx模型查看。 b. 模型参数即验证结果 其中,YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x为五种类型的预训练模型,其包含的检测类别相…

呆滞物料规范管理了,问题就好办了

对于制造企业来说&#xff0c;库存是生存和发展的重要保障&#xff0c;过高的库存会占用企业大量的资金和管理成本&#xff0c;影响企业的正常生产&#xff0c;然而多数中小制造企业还在用人工干预管理&#xff0c;如何控制呆滞物料成为仓储管理的一大难题。 什么是呆滞料&…

Django 创建项目及应用

1&#xff0c;安装 Django pip install Django3.1.5 2&#xff0c;创建 Django项目 django-admin startproject myshop 3&#xff0c;创建 Django应用 python manage.py startapp app1 4&#xff0c;启动 Django项目 python .\manage.py runserver 到这里项目及应用创建…

Redis中的主从复制

分布式系统中的几种Redis部署方式 为了解决一个程序只部署在一个服务器上的单点问题&#xff1a; 可用性问题&#xff0c;如果这个机器挂了&#xff0c;就意味着服务就中断了 一个程序只部署在一台机器上&#xff0c;它的性能/支持的并发量也是有限的 所以&#xff0c;就引…