数据流依赖使用Airflow实现,服务器运行的Airflow版本是1.10,对应的文档在这里,其中有一个1.10.2版本的翻译文档在这里,1.10.2文档和1.10.0文档差别不大,可以作为辅助文档查看。
当前数据流的源代码在gitlab的gzdz/airflow-dags中,可以通过git命令将其克隆到本地,git clone ssh://git@68.32.100.97:1002/gzdz/airflow-dags
,克隆后可以使用IDEA或者PyCharm打开。由于Ariflow的依赖众多、windows和linux的依赖不同、且内网开发不便直接解决依赖,所以airflow-dags直接使用服务器的Python解释器作为项目开发的解释器。配置方式详见如何配置远程解释器环境-以Python和Airflow配置为例
项目的树状结构如下:
airflow-dags
|-- dags 放dag文件及udf文件的路径
|-- jar gzdrug-download程序的jar包及配置文件
|-- udf airflow-udf相关函数
|-- support_file airflow相关的支撑文件,附件
|-- adhoc 部分常用的查询
|-- airflowTest dag_id='airflowTest'的附件
|-- ddl Hive、Oracle的建表语句、ElasticSearch的mapping文件
|-- drug_monitor 毒情监测相关dag的附件目录,包括每日调度的毒情监测任务,每月调度端的毒情监测任务
每个dag文件都会有说明文档,说明文档在各个dag定义代码的前几行,简单说明了这个dag文件是做什么的。然后在定义中使用dag.doc_md = __doc__
实现将说明字符串赋值给
例如
# udf这个包Pycharm可能会提示错误
from udf.oracle_to_mysql import OracleToMysqlTransfer
首先python是解释型语言,没有编译的环节,即使依赖找不到也没有关系。其次这里的报错仅仅是在Pycharm环境报错,在服务器环境是不报错的,如果不想深入仅需要了解服务器解析的根目录和Pycharm解析的根目录不一样。其原因是服务器的解析路径airflow解析目录在哪里,而Pycharm解析的是git管理项目的根目录。由于这个不都就会导致Pycharm中的包提示找不到。但是我们是要将dag文件放到服务器去解析调度的,所以要以服务器路径为准。
这是由于airflow部分不能找到的依赖引起的,因为Pycharm找不到引用的包,如果编写时需要自动提示,可以对对应的Operator导入语句前增加.
符号,实现Pycharm识别,如下
- from udf.oracle_to_mysql import OracleToMysqlTransfer
+ from .udf.oracle_to_mysql import OracleToMysqlTransfer
但是请注意,编写完了之后需要删除刚刚增加的.
才上传到服务器,不在服务器会解析不成功。
如果先加入一个任务需要补之前的全量数据,可以参数市局全量数据下载下载全量数据,然后上传到HDFS中。最后编写一段sql将目前的全量单分区表变成按时间ds分区的表,这段sql可以参考gzdrug-data-query中生成的全量sql转换成按ds分区的转换方式。
airflow解析目录在97服务器中的/srv/dockerData/airflow/program
中
DataX是阿里巴巴开源的数据异构框架,可以实现异构数据源之间的数据同步,详细介绍请见datax官网,由于DataX中有部分bug,且阿里没有投入太多精力维护,所以我维护了一个分支,生产环境中是基于我的分支为基准的,他会定时发布,要获取最新的二进制文件请直接在release中下载
详见user-guild,关键步骤为下面几个:
python datax.py -r <YOUR_READER> -w <YOUR_WRITER>
python datax.py /path/to/job.json
目前datax部署的位置是97服务器的/root/datax
目录中,其中重要目录的职责是:
/root/datax
: home目录/root/datax/bin
: datax启动相关文件/root/datax/job
: datax配置文件相关目录,和airflow-dags中关于datax的配置文件路径一致使用python ./bin/datax.py –p"-D<PARAM_NAME>=<PARAM_VAL> -D<PARAM_NAME>=<PARAM_VAL>" ./job/job.json
向配置文件job.json
传递参数。参考链接
在datax如何使用中知道通过命令python datax.py -r <YOUR_READER> -w <YOUR_WRITER>
可以生成模板,如果模板不能满足需要,或者想要知道模板各个参数代表的值,可以在datax-support-data-channels中点击对应超链接查看全部的参数和具体含义。如果参数在datax-support-data-channels没有,可能是fork中修改的,到对应的目录中查看即可知道参数含义。
目前gzdrug-download存在几个可以改进的点:
目前hive-sql运行的任务都会在Spark Thrift Server(下文称STS)中运行,STS有三个节点运行,节点会常驻Yarn内存,表现为一直running状态。如果要查看各个任务的运行情况可以参照查看hive任务运行情况。
目前项目运行sql的方式很多,包括
select * from TABLE_NAME
,要改成select * from drug_monitor.TABLE_NAME
Query Editors -> Hive
,另一个是Notebooks -> test_SparkSql
。需要注意的是前者使用的是TeZ计算引擎,后者使用的是Saprk计算引擎,使用TeZ计算引擎会导致部分正在跑的sql不起作用(因为部分sql需要先配置spark环境变量然后运行sql)从可靠性由高到低分别是:使用beeline命令行运行 > 使用在线编辑工具编写sql > 使用Idea/Pycharm创建Hive-JDBC连接
cannot call methods on a stoppped SparkContext.
此时是因为当前连接的spark节点有故障,不能运行任务。这是一个可以改进的项目,详见spark-thrift-servers不能自动重启,遇到这个情况可以进行两个类型处理:
使用beeline直接运行sql是目前这套系统最可靠的运行方式。具体有什么方式请见运行hive-sql的方式,因为别的方式可能存在以下情况
Query Editors -> Hive
如何使用beeline连接hiveserver2,因为beeline是一个命令行,所以全部的命令都是通过命令行实现的,airflow的Hive任务本质上也是通过beeline提交的任务,所以在beeline中如果命令可以正常执行,那么在Airflow中也一定能正常执行。其中关于beeline的代理见beeline代理,如果连接有问题很可能是因为spark-thrift-servers不能自动重启,下面介绍如何使用beeline命令(这个命令不需要记忆,可以通过history | grep beeline
找到):
beeline -u jdbc:hive2://68.32.100.99:20000 -n hive
即可连接到beeline,注意大部分数据都放在drug_monitor
数据库中,故没有特殊情况下,一般连接上后就要运行use drug_monitor;
切换到目标数据库。这里的beeline版本低,所以使用beeline -u jdbc:hive2://68.32.100.99:20000/drug_monitor -n hive
在连接的时候指定数据库是无效的。由于命令有点长,仅在103机器设置了快捷方式,仅在103机器可以通过运行beeline-start
使用beeline,实现方式是在/etc/profile
增加一行alias beeline-start='beeline -u jdbc:hive2://68.32.100.99:20000 -n hive'
docker run --name myBeeline --rm -it --entrypoint=./beeline -u jdbc:hive2://68.32.100.99:20000 -n hive
即可连接。如果运行命令后报错docker: Error response from daemon: Conflict
,则说明这个容器名已经被使用,可以修改运行命令参数--name myBeeline
的myBeeline
变成唯一名称即可运行。同时建议定期清理服务器中的beeline容器,可以运行docker rm -f $(docker ps --filter ancestor=sutoiku/beeline -aq)
为了实现高可用,引入了HAProxy作为代理,账户名密码为 admin/admin ,他会轮询三个长时间运行的STS服务。但是由于spark-thrift-servers不能自动重启,所以使用beeline -u jdbc:hive2://68.32.100.99:20000 -n hive
连接的时候可能会有运行hive-sql可能出现的情况出现的特殊情况发生,如出现了只需要按照连接中的解决方案解决即可
由spark-thrift-servers不能自动重启知道目前的自动重启无效,且STS可能会失败。如何才能知道实际正在运行的STS节点数?答案是通过Yarn页面。操作步骤是:进入Yarn页面,点击左侧栏Applications -> running
,查看在运行且Application Type
是Spar的应用数是多少,如果应用数小于3(正常值是3)则说明有部分STS任务已经挂了,此时可以通过Ambari重启全部的Spark服务
如果是通过beeline连接的任务,包括:命令行使用beeline连接、IDEA/Pycharm通过自定义Driver、airflow-HiveOperator,都是在Yarn的Applications -> running
右边app中,因为使用了beeline-porxy,所以需要分别点开正在运行的app去到Jobs页面查看当前任务的具体运行情况
项目有使用两个UDF,有一个自定义的,判断身份证是否有效、将15位的身份证转成18位什么证源代码找不到了,一个使用开源的udf,后面的那边有比较多常用的udf,可以作为官方udf的补充
查看HIVE数据HDFS路径下的文件有三个方法,其中两个是是在web页面查看,另一个是在命令行中查看,下面分别说明这三个方法,推荐程度由高到低分别是:
HUE -> HDFS Browser -> <选择到指定目录>
,选择的目录为/apps/hive/warehouse/[数据库/]<表名>
,如果有分区的表需要点击下一级的文件夹,如果没有分区的表文件夹中显示的内容即是表的数据文件。这个比Ambari中查看的好处是可以记录上级文件目录,Ambari中查看不能记忆上级文件目录
Ambari -> Files View -> <选择到指定目录>
,选择的目录为/apps/hive/warehouse/[数据库/]<表名>
,如果有分区的表需要点击下一级的文件夹,如果没有分区的表文件夹中显示的内容即是表的数据文件。这个比命令行查看的好处是有可视化页面查看,响应比命令行快
hdfs dfs -ls /apps/hive/warehouse/[数据库/]<表名>
分两种情况,从市局中导入的数据和从RDBMS中导入的数据:
ORC
文件格式,不要使用Parquet
格式,目前内网中的DataX二进制文件不支持todo
目前是使用DataX完成这项操作,具体的操作见DataX部分,如果需要实现定时调度请参考DataX任务配置到Airflow中
将HIVE运行结果导出到本地是一个常见的分析功能,目前全部的导出功能都是有缺陷,没有一个是好用的,仅有部分可用的功能推荐程度从高到低分别为
HUE -> Query Editors -> HIVE
,这里的可以导出select
语句的全部的数据,只需要运行了sql后在结果中的Export results
选择对应的格式就行。这个的缺点是计算殷勤是TeZ,有部分设置环境变量的语法不支持。超过1万行会很慢甚至死机To File
即可将导出到指定文件。这个的缺点是可以经常连接会断开,超过1万行会很慢甚至死机。set spark.sql.shuffle.partitions=1; insert overwrite table <TMP_TABLE> select <SELECT语句>
,然后去到HDFS-web页面路径 /apps/hive/warehouse/<TMP_TABLE>
找到生成的文件,点击下载将文件下载到本地使用gzdrug-data-query可以你更简单的完成建表和生成转换sql的语句,具体使用说明见README,完成市局历史数据和增量数据的下载主要是运行程序query_from_sj.py
。需要完成的步骤有(假设该资源对应的HIVE表是<TABLE_NAME>
):
query_from_sj.py
程序自动生成。自动生成<TABLE_NAME>_textfile
和<TABLE_NAME>
的建表语句,可以将这里生成的sql粘贴到airflow-dags中的airflow-dags/support_file/ddl/hive/download.sql
文件的指定路径中,然后在Hive中运行这两个创建语句创建对应的表query_from_sj.py
程序自动生成,可能需要部分修改。自动生成从<TABLE_NAME>_textfile
到<TABLE_NAME>
这一步的转换语句,这不的操作一般是去重 去掉字段两边的空格 将15位身份证转成18位,其中去重 去掉字段两边的空格都可以直接沿用自动生成的sql,但是将15位身份证转成18位需要人为手动添加,因为程序并不知道那个是身份证字段。将该生成的脚本放到airflow-dags中的airflow-dags/support_file/drug_monitor/daily/main/<TABLE_NAME>.sql
文件,一般这个路径需要新建
airflow-dags/dags/drug_monitor.py
中找到变量tablename_in_hiveserver2_extract_from_sj_increment
的声明,在声明列表最后新增一个值,命名为<TABLE_NAME>
no status
状态的任务目前没有比较高效的实现方式,比较理想的方式是在gzdrug-download进行扩展,详细方式见gzdrug-download下载全量数据并上传到HDFS
目前Hive任务在dag_id='drug_monitor'
的流程中已经形成了模板,只需要增加如下步骤即可
增加sql文件:写SQL,并将文件放在airflow-dags/support_file/drug_monitor/daily/main
文件夹下
引用SQL文件:一般的hive任务只需要在hive_op
字典中增加一个key即可,即
hive_op = dict.fromkeys([
# dim
'dev_dz_route,
+ '<YOUR_SQL_FILE_CREATE_IN_STEP_ONE>'
])
配置任务的依赖:在dag view的web页面找到对应的依赖,然后配置上即可,如hive_op['prev_task'] >> hive_op['<YOUR_TASK>']
在指定的ssh_conn_id
中运行指定的bash命令command
datax运行原理请见datax,目前Datax任务在dag_id='drug_monitor'
的流程中已经形成了模板,模板实现了:
python datax.py job.json
如果有新的任务需要加入,只需要增加如下步骤即可
增加配置文件:写SQL,并将文件放在airflow-dags/support_file/drug_monitor/daily/json
文件夹下
引用配置文件:一般的hive任务只需要在hive_op
字典中增加一个key即可,即
datax_daily_sync_op = dict.fromkeys([
"dz_call2es_daily",
+ "<YOUR_CONF_FILE>"
])
配置任务的依赖:在dag view的web页面找到对应的依赖,然后配置上即可,如hive_op['prev_task'] >> datax_daily_sync_op['<YOUR_TASK>']
目前使用的PGIS相关服务包括地图服务和数据访问更新服务,地图服务是低啊用PGIS地图的服务(这个家如应该更加懂,就不展开解释),PGIS数据访问更新服务是访问PGIS对外提供的数据的服务。PGIS的联系人见pgis服务接口人
数据访问更新服务可以访问PGIS对外提供的数据:
PGIS文档/PGIS警务辖区图层整理.xls
中写了一个解析简单的解析文件,用于PGIS数据访问更新服务的response,对应在gitlab/gzdrug-data-query中的query_from_pgis
,直接在Pycharm中运行main.py
文件就能解析对应的内容,conf.json
文件是对应的配置文件,使用xpath
解析数据,理论上可以解析返回的数据数据,只需要配置正确即可
项目和很多使用的软件都是通过docker启动的,一般的启动方式是docker-compose。使用这个方式启动的服务有
对于上面这些任务,如果需要运行/停止/重运行的话,仅需要找到docker-compose的配置文件,然后运行docker-compose up/down/restart
就能实现对应的运行/停止/重运行
操作,部分配置文件中可能有多个docker-compose-*.yml
开头的文件,则需要指定配置文件运行docker-compose -f <docker-compose-you-want-to-run.yml> up/down/restart
(启动的时候要加-d
操作)。不管是96还是97的机器,配置文件的路径都是/srv/deploy/docker-repo
,配置文件通过git管理,对应的版本库是docker-repo。进入配置文件目录可以看到都是以服务名命名的文件夹,所以需要启动对应的服务只需要cd <服务名>
然后运行docker-compose
命令即可,下面以mysql为例
# 到docker-compose配置文件的根目录
$ cd /srv/deploy/docker-repo
# 到mysql服务的配置文件目录
$ cd mysql
# 停止运行
$ docker-compose down
# 运行
$ docker-compose up -d
# 重运行
$ docker-compose restart
前后端部署也是使用docker部署方式,但是组织形式和别的不一样。前后端的配置文件,定义文件都在对应的代码库中,即gitlab/gzdrug-openapi和gitlab/gzdrug-client中。部署前后端是通过运行各自代码库中tool
的bash脚本完成的。一般命令是./tool -d <BRANCH>
完成对应分支的发布。他主要通过以下方式实现部署
tool
的机器中完成前后端源码的编译(本地机器),这要求本地机器必须有对应的开发环境和依赖。期间可能会修改部分文件,如前端配置对应的后端,后端设置的properties文件scp
命令将编译好的文件、Dockerfile、docker-compose.yml、.env等部署依赖文件发送到97服务器中docker-compose up -d
完成部署不管96还是97的中启动的docker服务,一般数据文件都是放在/srv/dockerData/
中,和启动的配置文件一样,以服务名作为文件夹,每个文件夹下放对应服务的数据文件
路径在/srv/dockerData/attachment
,如果有新的文件需要放在附件服务器,只需放到97机器的这个目录就行。这个在gitlab/docker-repo中的attachment/docker-compose.yml
可以看到对应的定义。
大数据平台组件的重启方式一般是直接在Ambari选择对应的服务然后重启,停止和启动也是一样的流程。具体的方式为,进入Ambari页面,在左侧栏选择你需要操作的服务,然后在右上角的Service Actions
中选择对应的操作类型,以Spark的重启为例进入Ambari -> 点击左侧Spark -> Service Actions -> Restart All
xmind中的数据量
目前市局的下载任务是使用gzdrug-download编译的jar包,将数据从市局大数据平台下载到jar包指定目录,然后使用HDFS Java API将本地文件上传到HDFS路径中。这个过程中有一步是可以跳过的,就是将文件下载到本地目录这个操作。理想的情况下应该是gzdrug-download从市局接口下载下来直接写入HDFS目录中,跳过下载本地文件的操作。具体的实现思路
注意要点:
msck table <TABLE_NAME>
,msck命令详细见这里
目前下载某个表的全量数据是通过市局全量数据下载的方式实现的,这个实现方式不太理想,理想的方式是类似gzdrug-download直接上传到HDFS那样的。通过运行java -jar gzdrug-download.jar history
命令,会自动实现任务每天切片,变成类似java -jar gzdrug-download.jar 20150101 20150102
java -jar gzdrug-download.jar 20150102 20150103
一直到 java -jar gzdrug-download.jar <昨天> <今天>
,然后根据gzdrug-download直接上传到HDFS的描述直接将文件上传到HDFS跳过本地文件
目前判断身份证是否有效的UDF放在服务器路径/usr/hdp/2.5.3.0-37/spark/udf/UDF-1.0-SNAPSHOT.jar
中,但是这个UDF的源代码找不到了,找到源码了,放在gitlab/udf,后面我会再去找找看,但是这里将其的实现简单的说下:
之前没有做但是应该做的:
现在的情况是,Spark Thrift Servers(下面简称STS)配置使用的是3个节点,Ambari配置了如果有任意一个节点挂了就会重启节点,按照道理来说这样的配置可以实现当STS服务挂了之后自动重启,但这个功能没有实现。所以这样会引发一系列的问题:
restart_spark
目前部分Spring Boot依赖的Word或者Excel文件放在resources
目录不能调用,所以只能放在docker启动的服务中的nginx文件下载器中,这样可以实现功能,但是最好的还是建议放在resources
中,因为是项目内部的依赖
目前后端基于mysql中的dz_area_code
和dz_area_code_relation
实现了简单的全国各地行政区划的代码,和自定义人员类型的功能(如自定义外来涉毒重点人员),但是这样功能应该是要展示在前端页面中,让用户自己编辑,目前页面是不支持这个功能的。另外,目前两张表的情况不能满足需要,应该加多一张表,把dz_area_code
作为行政区代码和中文对应实体表,吧dz_area_code_relation
作为用户自定义人员群体类型实体表,新增一张关联表,用于获取自定义人员全部的行政区。(和用户 角色 用户角色关系
类似)
另外因为行政区有废弃的代码,增加一张dz_area_code_old
用于储存旧的代码,这样方便扩展
dz_people_mobile
中的数据需要增加dev_dz_mobile
中的数据dev_dz_people_zipper
中的drug_type
目前仅有NIS
类型的数据,按照道理应该有吸毒``涉毒
相关的数据的dz_call_drug_monitor_adapter
中有重复的pk
数据,意味着dz_call
中也有重复的数据,按照道理应该不存在重复的pk
目前已经把街镇毒情全部切换到了ES统计了,但是街镇毒情的明细没有来得及完成,大概看了下:
route
及call
对应的值cityEarlyWarningNumber
方法,实现支持station
和queryTime
支持时间段有时需要配置远程的解释器/JDK作为开发环境,这种情况下如何配置IDEA、PyCharm的默认解释器呢。下面以Python + Airflow配置为例,由于服务器Ariflow运行在d
ocker中,所以要使用远程解释器则要先配置本地配置docker-remote-api,然后配置对应的解释器,路径是setting -> Project: airflow-dags -> Project Interpreter -> Add -> -> Docker
,然后在Image name中选择zhongjiajie/airflow-1.10
这个镜像作为远程解释器镜像
首先确保docker-remoteapi正在开启状态,判断方式是在对应的服务器中运行netstat -anp | grep LISTRN | grep dockerd
,如果能看到有tcp6类型且有对应端口的dockerd正在运行就说明已经开启了,一般的端口为2375,如果没有开启请参考如何开启docker-remote-api。确保开启后,回到IDEA/PyCharm
bash中运行
vim /etc/docker/daemon.json
然后增加如下配置
{
+ "hosts": [
+ "tcp://0.0.0.0:2375",
+ "unix:////var/run/docker.sock"
+ ]
}
重新加载配置并重启docker
systemctl daemon-reload
systemctl restart docker
如果96,97机器有部分服务不能访问,请检查服务的开启方式,前后端,mysql、redis数据库,gitlab,airflow,ftp,附件服务器都是使用
目前airflow dag的部署是直接将dag及其依赖文件通过Pycharm upload 到服务器中,交给服务器解析。具体的方式为Pycharm -> Version Control -> 选中全部的修改 -> 右键 -> Deployment -> Upload to -> 选择对应的服务器
。如果想要自动同步修改的文件到服务器则启动Pycharm -> Tools -> Deployment -> 勾选Automatic Upload(always)
。一般将配置文件上传到服务器后dag页面不会马上解析出来,可能要等待1-3分钟。但是实际运行运行已经是加入了依赖了,只是渲染页面没有及时渲染
FTP使用Docker启动,开启方式见Docker启动服务,这里是因为这个镜像不支持中文,如果想要实现中文则需要找一个别的Docker镜像并通过Docker镜像离线传到开发机上传到服务器再使用
因为开发机没有互联网环境,导致创建新的docker镜像的会比较困难。这里给出一个解决方案,假设开发机需要导入的镜像是openjdk
# 在可以连接互联网且有docker的机器拉取对应的镜像
$ docker pull openjdk:8-jre
# 等待上面命令运行完,将镜像导出成本地文件
$ docker save openjdk:8-jre | gzip > /path/to/openjdk-8-jre.gz
# 将上面命令生成的gz压缩包传输到服务器需要该docker镜像的机器,并导入
$ docker load -i /path/to/openjdk-8-jre.gz
分情况考虑,进行如下步骤检查:
ping 68.32.100.96
,如果不能则说明服务器有问题,联系机房相关人员服务器机房接口人,如果可以则说明是我们的服务问题,进行下一步docker ps | grep mysql
,如果没在运行证明是服务挂了,重启服务即可,重试方式见docker启动的服务部分。如果服务还在运行,进行下一步df -h
检查机器磁盘空间,mysql仅使用了ssd,所以进需要关注/
节点的使用率,如果磁盘没有空间了,则要释放空间。步骤如下:
停止mysql服务,见docker启动的服务
删除/
目录中的部分文件(一般也没有别的文件,只能删除mysql数据文件,具体位置见docker数据目录)
# 进入mysql数据目录
$ cd /srv/dockerData/mysql/datadir/gzga_dev
# 按照数据文件大小排序
$ ls -lhS | less
# 逐个检查是否有可以删除的文件 如果有的话就删除文件 如果mysql的表是innodb的储存引擎,可以仅删除ibd文件 这里以 dz_wj_collect_call 表为例
$ rm dz_wj_collect_call.ibd
# 重新检查空间
$ df -h
# 如果已经有空间则重启mysql,看是否可以连上,如果没有空间继续回到删除文件操作
$ cd /srv/deploy/docker-repo/mysql
$ docker-compose up
分成两个情况,一是查看一台机器安装了什么服务,一是查看一个服务分别安装在什么机器
summary
页面即可看到机器安装了什么服务summary
,点击对应的服务,即可跳转到该服务分别安装在了什么机器中方式是database
中新建一个Driver
,然后用这个Driver
通过JDBC连接HIVE。方法如下:
安装程序 -> Hive
有相关的依赖,将其下载到本地IDEA/Pycharm -> database -> 点击+号 -> Driver -> Driver files -> 选择Hive-jdbc hadoop-common -> URL templates填写jdbc-str.txt中的模板 -> Class要选择对应的值 -> namet中填写'HIVE' -> Apply
IDEA/Pycharm -> database -> 点击+号 -> Data Source -> HIVE -> 填写HOST PORT USERNAME
上面三步即可完成连接。第三步不需要Test,test会不成功,直接进入Console
运行select 1;
作为测试
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。