热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

大数据之ES:简介与Window部署、Linux单机和Linux集群部署以及集群部署问题

记录下,部分叙述说明参考网上资源和尚硅谷开放资源,如有侵权,请联系删除文章目录简介全文搜索引擎ElasticsearchAndSolrES

记录下,部分叙述说明参考网上资源和尚硅谷开放资源,如有侵权,请联系删除



文章目录

  • 简介
    • 全文搜索引擎
    • Elasticsearch And Solr
    • ES OR Solr
    • Elasticsearch 应用案例
  • 安装部署
    • Windows安装
    • Linux单机安装
    • Linux集群安装
  • 集群启动异常问题
    • 集群不能发现
  • 数据格式映射


简介

ES是分布式、RESTful风格的搜索和数据分析引擎。作为The Elastic Stack的核心

The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。

能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视

化。Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 Elastic

Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上

百台服务器,处理 PB 级别的数据。


全文搜索引擎

Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:


  • 搜索的数据对象是大量的非结构化的文本数据。

  • 文件记录量达到数十万或数百万个甚至更多。

  • 支持大量基于交互式文本的查询。

  • 需求非常灵活的全文搜索查询。

  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。

  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。

为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎

这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。


Elasticsearch And Solr

Lucene 是 Apache 软件基金会 Jakarta 项目组的一个子项目,提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在 Java 开发环境里 Lucene 是一个成熟的免费开源工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。

但 Lucene 只是一个提供全文搜索功能类库的核心工具包,而真正使用它还需要一个完善的服务框架搭建起来进行应用。目前市面上流行的搜索引擎软件,主流的就两款:ElasticsearchSolr,这两款都是基于 Lucene 搭建的,可以独立部署启动的搜索引擎服务软件。由于内核相同,所以两者除了服务器安装、部署、管理、集群以外,对于数据的操作 修改、添加、保存、查询等等都十分类似。

在使用过程中,一般都会将 Elasticsearch 和 Solr 这两个软件对比,然后进行选型。这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 - Lucene构建的

但它们又是不同的。像所有东西一样,每个都有其优点和缺点:
在这里插入图片描述


  • 二者安装都很简单;
  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
  • Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。

ES OR Solr


  • ES由于易于使用,Elasticsearch 在新开发者中更受欢迎。

  • 如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择

  • 如果需要分布式索引,则需要选择 Elasticsearch。对于需要良好可伸缩性和以及性能分布式环境,Elasticsearch 是更好的选择。

  • Elasticsearch 在开源日志管理用例中占据主导地位,许多组织在 Elasticsearch 中索引它们的日志以使其可搜索。

  • 如果需要监控和指标查看,那么请使用 Elasticsearch,因为相对于 Solr,Elasticsearch 暴露了更多的关键指标


Elasticsearch 应用案例


  • GitHub: 2013 年初,抛弃了 Solr,采取 Elasticsearch 来做 PB 级的搜索。“GitHub 使用Elasticsearch 搜索 20TB 的数据,包括 13 亿文件和 1300 亿行代码”。

  • 维基百科:启动以 Elasticsearch 为基础的核心搜索架构

  • SoundCloud:“SoundCloud 使用 Elasticsearch 为 1.8 亿用户提供即时而精准的音乐搜索服务”。

  • 百度:目前广泛使用 Elasticsearch 作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部 20 多个业务线(包括云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大 100 台机器,200 个 ES 节点,每天导入 30TB+数据。

  • 新浪:使用 Elasticsearch 分析处理 32 亿条实时日志。

  • 阿里:使用 Elasticsearch 构建日志采集和分析体系。

  • Stack Overflow:解决 Bug 问题的网站,全英文,编程人员交流的网站。


安装部署


Windows安装


  • 下载

    Elasticsearch 的官方地址:https://www.elastic.co/cn/

    建议下载使用半年前的版本,比较稳定

    这里使用的是7.8.0版本

  • 安装

    安装比较简单,直接解压即可

  • 启动服务

    进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务

    注意:9300 端口为 Elasticsearch 集群间组件的通信端口,9200 端口为浏览器访问的http协议RESTful端口。

  • 测试访问

    浏览器(推荐使用谷歌浏览器),输入地址:http://localhost:9200,测试结果

{"name" : "DESKTOP-HC495PP","cluster_name" : "elasticsearch","cluster_uuid" : "Ebmrplk5TOi06oKvLXbPcA","version" : {"number" : "7.8.0","build_flavor" : "default","build_type" : "zip","build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65","build_date" : "2020-06-14T19:35:50.234439Z","build_snapshot" : false,"lucene_version" : "8.5.1","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

  • windows版本常见问题

    • Elasticsearch 是使用 java 开发的,且 7.8 版本的 ES 需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,果系统配置 JAVA_HOME,那么使用系统默认的 JDK,如果没有配置使用自带的 JDK,一般建议使用系统配置的 JDK。

    • 双击启动窗口闪退,通过路径访问追踪错误,如果是“空间不足”,请修改config/jvm.options 配置文件

      # 设置 JVM 初始内存为 1G。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存
      # Xms represents the initial size of total heap space
      # 设置 JVM 最大可用内存为 1G
      # Xmx represents the maximum size of total heap space
      -Xms1g
      -Xmx1g


Linux单机安装


  • 下载

    同上地址,使用7.8.0版本

  • 上传到linux目录

  • 解压

    # 解压缩
    tar -zxvf elasticsearch-7.8.0-linux-x86_64.tar.gz -C /opt/module
    # 改名
    mv elasticsearch-7.8.0 es

  • 创建用户

    因为安全问题,es不允许root用户直接运行

    个人演示使用mym用户,没有非root用户时可以按照如下规则创建es用户

    useradd es #新增 mym 用户
    passwd es #为 mym 用户设置密码
    userdel -r es #如果错了,可以删除再加
    chown -R es:es /opt/module/es #文件夹所有者

  • 修改配置文件

    修改/opt/module/es/config/elasticsearch.yml 文件

    # 加入如下配置
    cluster.name: elasticsearch
    node.name: node-1
    network.host: 0.0.0.0
    http.port: 9200
    cluster.initial_master_nodes: ["node-1"]

    修改/etc/security/limits.conf

    这里的es指的是es用户,而不是es程序,若用的是其他用户记得修改

    # 每个进程可以打开的文件数的限制
    es soft nofile 65536
    es hard nofile 65536

    修改/etc/security/limits.d/20-nproc.conf

    这里的es指的是es用户,而不是es程序,若用的是其他用户记得修改

    # 每个进程可以打开的文件数的限制
    es soft nofile 65536
    es hard nofile 65536
    # 操作系统级别对每个用户创建的进程数的限制
    * hard nproc 4096
    # 注:* 带表 Linux 所有用户名称

    以上配置改了需要重启服务才生效

    修改/etc/sysctl.conf

    # 在文件中增加下面内容
    # 一个进程可以拥有的 VMA(虚拟内存区域)的数量,默认值为 65536
    vm.max_map_count=655360

    重新加载

    sysctl -p

  • 启动ES服务

    记得使用es或非root用户上述配置使用的用户去启动

    cd /opt/module/es/
    #启动
    bin/elasticsearch
    #后台启动
    bin/elasticsearch -d

    (1)若启动报错,原因是java版本不对,es7.8要求java11,个人系统是java8

    [mym@mini1 es]$ bin/elasticsearch
    future versions of Elasticsearch will require Java 11; your Java version from [/usr/local/java8/jre] does not meet this requirement

    修改es读取的jdk版本,es自带一个jdk,让他读自己的

    vi bin/elasticsearch-env把如下内容加到前面

    export JAVA_HOME=/opt/module/es/jdk
    export PATH=$JAVA_HOME/bin:$PATHif [ -x "$JAVA_HOME/bin/java" ]; thenJAVA="/opt/module/es/jdk"
    elseJAVA=`which java`
    fi

    (2)若启动报错如下

    [mym@mini1 bin]$ bin/elasticsearch
    Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.nio.file.FileAlreadyExistsException: /opt/module/es/config/elasticsearch.keystore.tmp
    Likely root cause: java.nio.file.FileAlreadyExistsException: /opt/module/es/config/elasticsearch.keystore.tmpat java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:94)at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:478)at java.base/java.nio.file.Files.newOutputStream(Files.java:224)at org.apache.lucene.store.FSDirectory$FSIndexOutput.<init>(FSDirectory.java:410)at org.apache.lucene.store.FSDirectory$FSIndexOutput.<init>(FSDirectory.java:406)at org.apache.lucene.store.FSDirectory.createOutput(FSDirectory.java:254)at org.elasticsearch.common.settings.KeyStoreWrapper.save(KeyStoreWrapper.java:488)at org.elasticsearch.bootstrap.Bootstrap.loadSecureSettings(Bootstrap.java:259)at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:349)at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161)at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127)at org.elasticsearch.cli.Command.main(Command.java:90)at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126)at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)

    解决&#xff1a;提示文件已经存在&#xff0c;应该是第一次启动失败后生成的&#xff0c;删掉/opt/module/es/config/elasticsearch.keystore.tmp即可

  • 关闭防火墙方便测试

    #暂时关闭防火墙
    systemctl stop firewalld
    #永久关闭防火墙
    systemctl enable firewalld.service #打开放货抢永久性生效&#xff0c;重启后不会复原
    systemctl disable firewalld.service #关闭防火墙&#xff0c;永久性生效&#xff0c;重启后不会复原

  • 测试

    浏览器中输入地址&#xff1a;http://192.168.2.201:9200/

    响应如下

    {"name" : "node-1","cluster_name" : "elasticsearch","cluster_uuid" : "t8AkE4PSQ9OSJeUinZPGDA","version" : {"number" : "7.8.0","build_flavor" : "default","build_type" : "tar","build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65","build_date" : "2020-06-14T19:35:50.234439Z","build_snapshot" : false,"lucene_version" : "8.5.1","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
    }


Linux集群安装


  • 下载并解压并三台机器分发

  • 每台机器记得创建es用户&#xff0c;不能用root

  • 修改配置文件

    这里与单机部署不一样配置

    修改/opt/module/es/config/elasticsearch.yml 文件&#xff0c;分发文件

    # 加入如下配置
    #集群名称
    cluster.name: cluster-es
    #节点名称&#xff0c;每个节点的名称不能重复
    node.name: node-1
    #ip 地址&#xff0c;每个节点的地址不能重复
    network.host: mini1
    #是不是有资格主节点
    node.master: true
    node.data: true
    http.port: 9200
    # head 插件需要这打开这两个配置
    http.cors.allow-origin: "*"
    http.cors.enabled: true
    http.max_content_length: 200mb
    #es7.x 之后新增的配置&#xff0c;初始化一个新的集群时需要此配置来选举 master 这里集群里的都配置同一个
    cluster.initial_master_nodes: ["node-1"]
    #es7.x 之后新增的配置&#xff0c;节点发现
    discovery.seed_hosts: ["mini1:9300","mini2:9300","mini3:9300"]
    gateway.recover_after_nodes: 2
    network.tcp.keep_alive: true
    network.tcp.no_delay: true
    transport.tcp.compress: true
    #集群内同时启动的数据任务个数&#xff0c;默认是 2 个
    cluster.routing.allocation.cluster_concurrent_rebalance: 16
    #添加或删除节点及负载均衡时并发恢复的线程个数&#xff0c;默认 4 个
    cluster.routing.allocation.node_concurrent_recoveries: 16
    #初始化数据恢复时&#xff0c;并发恢复线程的个数&#xff0c;默认 4 个
    cluster.routing.allocation.node_initial_primaries_recoveries: 16

    修改/etc/security/limits.conf&#xff0c;分发文件

    注意es是用户名如果使用其他用户记得修改正确

    # 在文件末尾中增加下面内容
    es soft nofile 65536
    es hard nofile 65536

    修改/etc/security/limits.d/20-nproc.conf&#xff0c;分发文件

    注意es是用户名如果使用其他用户记得修改正确

    # 在文件末尾中增加下面内容
    es soft nofile 65536
    es hard nofile 65536
    * hard nproc 4096
    # 注&#xff1a;* 带表 Linux 所有用户名称

    修改/etc/sysctl.conf

    # 在文件中增加下面内容
    vm.max_map_count&#61;655360

    重新加载

    sysctl -p

  • 启动软件

    分别在不同的节点上启动软件

    #启动
    bin/elasticsearch
    #后台启动
    bin/elasticsearch -d

    记得如果jdk不是jdk11&#xff0c;记得修改elasticsearch-env文件修改es使用自己的jdk&#xff0c;修改内容如下

    export JAVA_HOME&#61;/opt/module/es/jdk
    export PATH&#61;$JAVA_HOME/bin:$PATHif [ -x "$JAVA_HOME/bin/java" ]; thenJAVA&#61;"/opt/module/es/jdk"
    elseJAVA&#61;&#96;which java&#96;
    fi

  • 测试集群

    个人跑的时候报错了

    [mym&#64;mini3 es]$ bin/elasticsearch -d
    [mym&#64;mini3 es]$ ERROR: [1] bootstrap checks failed
    [1]: max number of threads [3851] for user [mym] is too low, increase to at least [4096]
    ERROR: Elasticsearch did not exit normally - check the logs at /opt/module/es/logs/cluster-es.log

    意思是上述几个配置项有没生效的&#xff0c;重启下服务器就好了

    jps可以看到一个Elasticsearch进程

    浏览器中输入地址&#xff1a;http://192.168.2.201:9200

    响应如下

    {"name" : "node-1","cluster_name" : "cluster-es","cluster_uuid" : "t8AkE4PSQ9OSJeUinZPGDA","version" : {"number" : "7.8.0","build_flavor" : "default","build_type" : "tar","build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65","build_date" : "2020-06-14T19:35:50.234439Z","build_snapshot" : false,"lucene_version" : "8.5.1","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
    }

    查看集群节点&#xff1a;http://192.168.2.201:9200/_cat/nodes

    响应

    ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
    192.168.2.201 16 94 15 1.70 1.14 0.80 dilmrt - node-1
    192.168.2.203 38 93 4 0.17 0.21 0.21 dilmrt - node-3
    192.168.2.202 18 93 4 0.22 0.51 0.41 dilmrt * node-2


集群启动异常问题


集群不能发现

现象是每台服务各自为政&#xff0c;没有互相发现为集群加入。查看启动日志发现Cluster UUID都不一样&#xff0c;说明各自作为一个集群初始化节点了&#xff0c;都在等别人加入&#xff0c;自己都是master&#xff01;&#xff01;&#xff01;

发生这个的原因是一开始如下配置每个节点都配置单独自己了&#xff0c;导致每个节点启动时把自己作为master初始化集群了。这里所有节点都要配置一摸一样的&#xff0c;配一个或多个都可以&#xff0c;这只在集群初始化时为了选一个master用&#xff0c;之后有新节点或者集群重启时这个配置就不会被用到。

#es7.x 之后新增的配置&#xff0c;初始化一个新的集群时需要此配置来选举 master 这里集群里的都配置同一个
cluster.initial_master_nodes: ["node-1"]

解决&#xff1a;需要把es目录下的data目录里的nodes删除&#xff0c;里面有初始化的集群信息&#xff0c;删掉nodes目录&#xff0c;并改好配置重启即可


数据格式映射

Elasticsearch 是面向文档型数据库&#xff0c;一条数据在这里就是一个文档。为了方便大家理解&#xff0c;我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比


ESMysql
Index&#xff08;索引&#xff09;Database&#xff08;数据库&#xff09;
Type&#xff08;类型&#xff09;Table&#xff08;表&#xff09;
Documents&#xff08;文档&#xff09;Row&#xff08;行&#xff09;
Fields&#xff08;字段&#xff09;Column&#xff08;列&#xff09;

ES 里的 Index 可以看做一个库&#xff0c;而 Types 相当于表&#xff0c;Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化&#xff0c;Elasticsearch 6.X 中&#xff0c;一个 index 下已经只能包含一个type&#xff0c;Elasticsearch 7.X 中, Type 的概念已经被删除了。


推荐阅读
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 深入解析:存储技术的演变与发展
    本文探讨了从单机文件系统到分布式文件系统的存储技术发展过程,详细解释了各种存储模型及其特点。 ... [详细]
  • 对象存储与块存储、文件存储等对比
    看到一篇文档,讲对象存储,好奇,搜索文章,摘抄,学习记录!背景:传统存储在面对海量非结构化数据时,在存储、分享与容灾上面临很大的挑战,主要表现在以下几个方面:传统存储并非为非结 ... [详细]
  • 本文详细介绍了如何在PHP中使用Memcached进行数据缓存,包括服务器连接、数据操作、高级功能等。 ... [详细]
  • selenium通过JS语法操作页面元素
    做过web测试的小伙伴们都知道,web元素现在很多是JS写的,那么既然是JS写的,可以通过JS语言去操作页面,来帮助我们操作一些selenium不能覆盖的功能。问题来了我们能否通过 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • 一家位于长沙的知名网络安全企业,现面向全国诚聘高级后端开发工程师,特别欢迎具有一线城市经验的技术精英回归故乡,共创辉煌。 ... [详细]
  • 本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ... [详细]
  • 本文介绍了如何利用X_CORBA实现远程对象调用,并通过多个示例程序展示了其功能与应用,包括基础的Hello World示例、文件传输工具以及一个完整的聊天系统。 ... [详细]
  • 深入探讨:Actor模型如何解决并发与分布式计算难题
    在现代软件开发中,高并发和分布式系统的设计面临着诸多挑战。本文基于Akka最新文档,详细探讨了Actor模型如何有效地解决这些挑战,并提供了对并发和分布式计算的新视角。 ... [详细]
  • Redis:缓存与内存数据库详解
    本文介绍了数据库的基本分类,重点探讨了关系型与非关系型数据库的区别,并详细解析了Redis作为非关系型数据库的特点、工作模式、优点及持久化机制。 ... [详细]
  • 8个IDC大数据基础定义解析丨IDC
    本文针对IDC数据行业相关名词术语进行解析,分为4组相关概念,希望大家读完 ... [详细]
  • 本文详细介绍了如何在Windows和Linux系统上配置Openfire服务器,包括安装步骤、数据库配置及端口映射等关键环节。 ... [详细]
author-avatar
荆州房产网
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有