首页 文章 精选 留言 我的

精选列表

搜索[实时风控],共10001篇文章
优秀的个人博客,低调大师

过滤器实栗 登录检测

项目结构 ![](https://melovemingming-1253878077.cos.ap-chengdu.myqcloud.com/blog-image/2019/03/2019-03-17%2004-56-15%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png) 代码如下 登录servlet package com.ming.servlrt; import com.ming.factory.DAOFactory; import com.ming.vo.User; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String path = "login.jsp"; // 接收userid内容 String userid = req.getParameter("userid"); // 接收userpass内容 String userpadd = req.getParameter("userpass"); // 保存返回信息 List<String> info = new ArrayList<String>(); if(userid == null || "".equals(userid)){ info.add("用户id不能为空"); } if(userpadd == null || "".equals(userpadd)){ info.add("密码不能为空"); } // 报错信息为0进行验证 if(info.size() == 0){ User user = new User(); user.setUserid(userid); user.setPassword(userpadd); try{ if(DAOFactory.getIuserDAOInstance().findLogin(user)){ info.add("登录成功!" + user.getName()); // 增加session会话 HttpSession session = req.getSession(); session.setAttribute("id", userid); }else{ info.add("登录失败"); } }catch (Exception e){ e.printStackTrace(); } } // 使用服务器端跳转, 保存数据 req.setAttribute("info", info); req.getRequestDispatcher(path).forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } } 对于登录的servlet增加了session 过滤器如下 package com.ming.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.IOException; // 首页过滤器 public class LoginFile implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 转型 因为默认的ServletRequest中未提供相关的方法,需要向下转型 HttpServletRequest request = (HttpServletRequest)servletRequest; // 获取到session HttpSession session = request.getSession(); // 判断登录 if(session.getAttribute("id") != null){ // 已经登录 filterChain.doFilter(servletRequest, servletResponse); }else{ // 跳转登录页登录 request.getRequestDispatcher("login.jsp").forward(servletRequest, servletResponse); } } @Override public void destroy() { } } 配置文件如下 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <filter> <filter-name>LoginFile</filter-name> <filter-class>com.ming.filter.LoginFile</filter-class> </filter> <filter-mapping> <filter-name>LoginFile</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.ming.servlrt.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/loginServlet</url-pattern> </servlet-mapping> </web-app> jsp文件如下 涉及 前端的js验证采用拦截click事件 <%@ page import="java.util.List" %> <%@ page import="java.util.Iterator" %><%-- Created by IntelliJ IDEA. User: ming Date: 19-3-16 Time: 下午11:07 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h2>用户登录程序</h2> <% List<String> info = (List<String>)request.getAttribute("info"); if(info != null){ Iterator<String> iterator = info.iterator(); while(iterator.hasNext()){ %> <h4><%=iterator.next()%></h4> <% } } %> <form action="loginServlet" method="post"> 用户id <input type="text" name="userid" id="uname"/> 密码 <input type="password" name="userpass" id="password"/> <input type="submit" value="登录" id="submit"/> <input type="reset" value="重置"/> </form> <script> let submit = document.getElementById("submit"); submit.onclick = (event) => { let uname = document.getElementById("uname").value; let password = document.getElementById("password").value; if(!(/^\w{1,15}/.test(uname))){ alert("用户id为5-15位"); return false; } if(!(/^\w{1,15}/.test(password))){ alert("密码必须为5-15位"); return false; } return true; } </script> </body> </html>

优秀的个人博客,低调大师

数据科学家实操之路

更多深度文章,请关注:https://yq.aliyun.com/cloud Kaggle最近进行了一项旨在评估数据科学和机器学习当前发展状况的调查。 他们收到了将近17000份答卷,并利用这些答卷做出了大量的分析。对于调查结果的分析报告,我并不感兴趣,我只是想看看这些调查结果是否对我这种想知道如何成为数据科学家的人来说是否有用。 如果你对分析过程并不感兴趣,而只想看看17000个行业专业人士的说法,那么请跳到本文的最后一节阅读结论。 否则,请继续阅读下文,看看我是如何得出结论的。 1. 导入和预处理 1.1. 导入数据 library(data.table)library(dplyr, warn.conflicts =FALSE)library(ggplot2)library(tibble) results <- as.tibbl

优秀的个人博客,低调大师

Excel连接openGauss数据库实操

目录 前言 一、通过excel 添加数据源访问openGauss 1、查看Excel版本 2、下载 ODBC驱动 3、安装ODBC驱动 4、添加ODBC数据源 5、在excel中添加数据源(访问openGauss) 二、通过excel 的VBA(宏)访问openGauss 1、宏权限设置 2、添加“开发工具” 3、创建按钮事件,访问openGauss 4、附代码说明(Vba) 三、Excel访问openGauss数据库应用场景举例 前言 互联网是个快节奏的时代,不懂得运用工具,将时间浪费在琐碎的事务中,将会极大的影响工作效率。 例如我们在工作中处理表格和数据时会经常用到Excel。基于此,本文将简单介绍一下Excel连接openGauss数据库的两种方式,欢迎交流。 一、通过excel 添加数据源访问openGauss 1、查看Excel版本 打开Excel程序, 文件——账户——关于excel,如截图。 2、下载 ODBC驱动 用户可以在华为云管理控制台下载GaussDB(DWS) 提供ODBC驱动程序(也可以使用开源的ODBC驱动程序)。 登录华为云管理控制台——在控制台左边列表,单机服务列表——大数据——数据仓库服务GaussDB(DWS)。 在左侧导航栏中,单击“连接管理”。 3)在“下载驱动程序”区域,选择一个驱动下载。 ODBC驱动:选择相应的版本,然后单击“下载”可以下载与集群版本匹配的ODBC驱动。单击“历史版本”可根据操作系统和集群版本下载相应版本的ODBC驱动,建议按集群版本进行下载。 本次测试下载的是“Microsoft Windows x86_64”驱动,其支持在以下系统中使用: Windows 7及以上。 Windows Server 2008及以上。 特别说明:Windows驱动只支持32位版本,可以在32或64位操作系统使用,但是应用程序必须为32位。 3、安装ODBC驱动 将下载的ODBC驱动解压,选则32位的进行安装。 安装过程:以管理员身份运行,然后一路点“Next”,直到 Finish 即可。 4、添加ODBC数据源 依次打开:控制面板-管理工具-ODBC Data Sources (32-bit)。 点击右边的添加按钮,找到 PostgreSQL Unicode,双击,填写连接信息(如下截图),点击Test。 提示成功后,点击保存(Save)。 5、在excel中添加数据源(访问openGauss) 依次点击:数据——其他来源——来自数据连接向导。 选择“ODBC DSN” 选择数据库和表 点“完成”,进到导入数据界面 点“属性” 按钮,进入“使用状况”选项卡,可设置数据刷新的规则。 进入“定义”选项卡,可进行编辑,获取相应的数据: 二、通过excel 的VBA(宏)访问openGauss 1、宏权限设置 打开excel 程序, 进入文件——选项——信任中心——信任中心设置: 起启用所有宏 信任对VBA工程对象模型的访问 2、添加“开发工具” 打开excel 程序, 进入文件——选项——自定义功能区 选择“开发工具” 打√。 3、创建按钮事件,访问openGauss 添加“连接openGauss” 按钮,通过如下截图过程进入宏的编辑界面: 编写Vba脚本,访问openGauss数据库: 4、附代码说明(Vba) Sub 连接openGauss() Dim cn As Object '定义数据链接对象 ,保存连接数据库信息 Dim rs As Object '定义记录集对象,保存数据表 Set cn = CreateObject("ADODB.Connection") '创建数据链接对象 Set rs = CreateObject("ADODB.RecordSet") '创建记录集对象,用于接收数据查询获得的结果集 Dim strCn As String '字符串变量 Dim strSQL As String '字符串变量 strCn = "DSN=openGauss;DATABASE=postgres;SERVER=192.168.52.3;PORT=26000;UID=omm2;SSLmode=disable;ReadOnly=0" '定义数据库链接字符串 strSQL = "SELECT id,name,age,address,salary FROM company1" '设置SQL语句 cn.Open strCn '打开连接 rs.Open strSQL, cn '读取数据库中的数据 Dim i As Integer, sht As Worksheet 'i为整数变量;sht 为excel工作表对象变量,指向某一工作表 i = 1 Set sht = ThisWorkbook.Worksheets("Sheet2") '循环读取数据并将数据显示到excel中 Do While Not rs.EOF '当数据指针未移到记录集末尾时,循环下列操作 sht.Cells(i, 1) = rs("id") '把当前记录的字段1的值保存到sheet1工作表的第i行第1列 sht.Cells(i, 2) = rs("name") '把当前字段2的值保存到sheet1工作表的第i行第2列 sht.Cells(i, 3) = rs("age") '把当前字段3的值保存到sheet1工作表的第i行第3列 sht.Cells(i, 4) = rs("address") '把当前字段4的值保存到sheet1工作表的第i行第4列 sht.Cells(i, 5) = rs("salary") '把当前字段5的值保存到sheet1工作表的第i行第5列 rs.MoveNext '把指针移向下一条记录 i = i + 1 'i加1,准备把下一记录相关字段的值保存到工作表的下一行 Loop '循环 rs.Close '关闭记录集,至此,程序将把某数据表的字段1和字段2保存在excel工作表sheet1的第1、2列,行数等于数据表的记录数 End Sub 三、Excel访问openGauss数据库应用场景举例 1、实现自动化实时监控相关数据,例如:跑批作业状态表、某项实时数据阈值监测等。 2、实现自动化业务报表展示等。 openGauss: 一款高性能、高安全、高可靠的企业级开源关系型数据库。

优秀的个人博客,低调大师

Rook 1.5.1 部署Ceph实操经验分享

一、Rook概述 1.1 Rook简介 Rook 是一个开源的cloud-native storage编排, 提供平台和框架;为各种存储解决方案提供平台、框架和支持,以便与云原生环境本地集成。目前主要专用于Cloud-Native环境的文件、块、对象存储服务。它实现了一个自我管理的、自我扩容的、自我修复的分布式存储服务。 Rook支持自动部署、启动、配置、分配(provisioning)、扩容/缩容、升级、迁移、灾难恢复、监控,以及资源管理。为了实现所有这些功能,Rook依赖底层的容器编排平台,例如 kubernetes、CoreOS 等。。 Rook 目前支持Ceph、NFS、Minio Object Store、Edegefs、Cassandra、CockroachDB 存储的搭建。 项目地址:https://github.com/rook/rook 网站:https://rook.io/ <!--more--> 1.2 Rook组件 Rook的主要组件有三个,功能如下: Rook Operator Rook与Kubernetes交互的组件 整个Rook集群只有一个 Agent or Driver Flex Driver 已经被淘汰的驱动方式,在安装之前,请确保k8s集群版本是否支持CSI,如果不支持,或者不想用CSI,选择flex. Ceph CSI Driver 默认全部节点安装,你可以通过 node affinity 去指定节点 Device discovery 发现新设备是否作为存储,可以在配置文件ROOK_ENABLE_DISCOVERY_DAEMON设置 enable 开启。 1.3 Rook & Ceph框架 Rook 如何集成在kubernetes 如图: 使用Rook部署Ceph集群的架构图如下: 部署的Ceph系统可以提供下面三种Volume Claim服务: Block Storage:目前最稳定; FileSystem:需要部署MDS,有内核要求; Object:部署RGW; 二、ROOK 部署 2.1 准备工作 2.1.1 版本要求 kubernetes v.11 以上 2.1.2 存储要求 rook部署的ceph 是不支持lvm direct直接作为osd存储设备的,如果想要使用lvm,可以使用pvc的形式实现。方法在后面的ceph安装会提到 为了配置 Ceph 存储集群,至少需要以下本地存储选项之一: 原始设备(无分区或格式化的文件系统) 原始分区(无格式文件系统) 可以 lsblk -f查看,如果 FSTYPE不为空说明有文件系统 可通过 block 模式从存储类别获得 PV 2.1.3 系统要求 本次安装环境 kubernetes 1.18 centos7.8 kernel 5.4.65-200.el7.x86_64 calico 3.16 2.1.3.1 需要安装lvm包 sudo yum install -y lvm2 2.1.3.2 内核要求 RBD 一般发行版的内核都编译有,但你最好确定下: foxchan@~$ lsmod|grep rbd rbd 114688 0 libceph 368640 1 rbd 可以用以下命令放到开机启动项里 cat > /etc/sysconfig/modules/rbd.modules << EOF modprobe rbd EOF CephFS 如果你想使用cephfs,内核最低要求是4.17。 2.2 部署ROOK Github上下载Rook最新release git clone --single-branch --branch v1.5.1 https://github.com/rook/rook.gits 安装公共部分 cd rook/cluster/examples/kubernetes/ceph kubectl create -f crds.yaml -f common.yaml 安装operator kubectl apply -f operator.yaml 如果放到生产环境,请提前规划好。operator的配置在ceph安装后不能修改,否则rook会删除集群并重建。 修改内容如下: # 启用cephfs ROOK_CSI_ENABLE_CEPHFS: "true" # 开启内核驱动替换ceph-fuse CSI_FORCE_CEPHFS_KERNEL_CLIENT: "true" #修改csi镜像为私有仓,加速部署时间 ROOK_CSI_CEPH_IMAGE: "harbor.foxchan.com/google_containers/cephcsi/cephcsi:v3.1.2" ROOK_CSI_REGISTRAR_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-node-driver-registrar:v2.0.1" ROOK_CSI_RESIZER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-resizer:v1.0.0" ROOK_CSI_PROVISIONER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-provisioner:v2.0.0" ROOK_CSI_SNAPSHOTTER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-snapshotter:v3.0.0" ROOK_CSI_ATTACHER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-attacher:v3.0.0" # 可以设置NODE_AFFINITY 来指定csi 部署的节点 # 我把plugin 和 provisioner分开了,具体调度方式看你集群资源。 CSI_PROVISIONER_NODE_AFFINITY: "app.rook.role=csi-provisioner" CSI_PLUGIN_NODE_AFFINITY: "app.rook.plugin=csi" #修改metrics端口,可以不改,我因为集群网络是host,为了避免端口冲突 # Configure CSI CSI Ceph FS grpc and liveness metrics port CSI_CEPHFS_GRPC_METRICS_PORT: "9491" CSI_CEPHFS_LIVENESS_METRICS_PORT: "9481" # Configure CSI RBD grpc and liveness metrics port CSI_RBD_GRPC_METRICS_PORT: "9490" CSI_RBD_LIVENESS_METRICS_PORT: "9480" # 修改rook镜像,加速部署时间 image: harbor.foxchan.com/google_containers/rook/ceph:v1.5.1 # 指定节点做存储 - name: DISCOVER_AGENT_NODE_AFFINITY value: "app.rook=storage" # 开启设备自动发现 - name: ROOK_ENABLE_DISCOVERY_DAEMON value: "true" 2.3 部署ceph集群 cluster.yaml文件里的内容需要修改,一定要适配自己的硬件情况,请详细阅读配置文件里的注释,避免我踩过的坑。 修改内容如下: 此文件的配置,除了增删osd设备外,其他的修改都要重装ceph集群才能生效,所以请提前规划好集群。如果修改后不卸载ceph直接apply,会触发ceph集群重装,导致集群异常挂掉 apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: # 命名空间的名字,同一个命名空间只支持一个集群 name: rook-ceph namespace: rook-ceph spec: # ceph版本说明 # v13 is mimic, v14 is nautilus, and v15 is octopus. cephVersion: #修改ceph镜像,加速部署时间 image: harbor.foxchan.com/google_containers/ceph/ceph:v15.2.5 # 是否允许不支持的ceph版本 allowUnsupported: false #指定rook数据在节点的保存路径 dataDirHostPath: /data/rook # 升级时如果检查失败是否继续 skipUpgradeChecks: false # 从1.5开始,mon的数量必须是奇数 mon: count: 3 # 是否允许在单个节点上部署多个mon pod allowMultiplePerNode: false mgr: modules: - name: pg_autoscaler enabled: true # 开启dashboard,禁用ssl,指定端口是7000,你可以默认https配置。我是为了ingress配置省事。 dashboard: enabled: true port: 7000 ssl: false # 开启prometheusRule monitoring: enabled: true # 部署PrometheusRule的命名空间,默认此CR所在命名空间 rulesNamespace: rook-ceph # 开启网络为host模式,解决无法使用cephfs pvc的bug network: provider: host # 开启crash collector,每个运行了Ceph守护进程的节点上创建crash collector pod crashCollector: disable: false # 设置node亲缘性,指定节点安装对应组件 placement: mon: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: ceph-mon operator: In values: - enabled osd: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: ceph-osd operator: In values: - enabled mgr: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: ceph-mgr operator: In values: - enabled # 存储的设置,默认都是true,意思是会把集群所有node的设备清空初始化。 storage: # cluster level storage configuration and selection useAllNodes: false #关闭使用所有Node useAllDevices: false #关闭使用所有设备 nodes: - name: "192.168.1.162" #指定存储节点主机 devices: - name: "nvme0n1p1" #指定磁盘为nvme0n1p1 - name: "192.168.1.163" devices: - name: "nvme0n1p1" - name: "192.168.1.164" devices: - name: "nvme0n1p1" - name: "192.168.1.213" devices: - name: "nvme0n1p1" 更多 cluster 的 CRD 配置参考: https://github.com/rook/rook/blob/master/Documentation/ceph-cluster-crd.md 执行安装 kubectl apply -f cluster.yaml # 需要等一段时间,所有pod都已正常启动 [foxchan@k8s-master ceph]$ kubectl get pods -n rook-ceph NAME READY STATUS RESTARTS AGE csi-cephfsplugin-b5tlr 3/3 Running 0 19h csi-cephfsplugin-mjssm 3/3 Running 0 19h csi-cephfsplugin-provisioner-5cf5ffdc76-mhdgz 6/6 Running 0 19h csi-cephfsplugin-provisioner-5cf5ffdc76-rpdl8 6/6 Running 0 19h csi-cephfsplugin-qmvkc 3/3 Running 0 19h csi-cephfsplugin-tntzd 3/3 Running 0 19h csi-rbdplugin-4p75p 3/3 Running 0 19h csi-rbdplugin-89mzz 3/3 Running 0 19h csi-rbdplugin-cjcwr 3/3 Running 0 19h csi-rbdplugin-ndjcj 3/3 Running 0 19h csi-rbdplugin-provisioner-658dd9fbc5-fwkmc 6/6 Running 0 19h csi-rbdplugin-provisioner-658dd9fbc5-tlxd8 6/6 Running 0 19h prometheus-rook-prometheus-0 2/2 Running 1 3d17h rook-ceph-mds-myfs-a-5cbcdc6f9c-7mdsv 1/1 Running 0 19h rook-ceph-mds-myfs-b-5f4cc54b87-m6m6f 1/1 Running 0 19h rook-ceph-mgr-a-f98d4455b-bwhw7 1/1 Running 0 20h rook-ceph-mon-a-5d445d4b8d-lmg67 1/1 Running 1 20h rook-ceph-mon-b-769c6fd76f-jrlc8 1/1 Running 0 20h rook-ceph-mon-c-6bfd8954f5-tbsnd 1/1 Running 0 20h rook-ceph-operator-7d8cc65dc-8wtl8 1/1 Running 0 20h rook-ceph-osd-0-c558ff759-bzbgw 1/1 Running 0 20h rook-ceph-osd-1-5c97d69d78-dkxbb 1/1 Running 0 20h rook-ceph-osd-2-7dddc7fd56-p58mw 1/1 Running 0 20h rook-ceph-osd-3-65ff985c7d-9gfgj 1/1 Running 0 20h rook-ceph-osd-prepare-192.168.1.213-pw5gr 0/1 Completed 0 19h rook-ceph-osd-prepare-192.168.1.162-wtkm8 0/1 Completed 0 19h rook-ceph-osd-prepare-192.168.1.163-b86r2 0/1 Completed 0 19h rook-ceph-osd-prepare-192.168.1.164-tj79t 0/1 Completed 0 19h rook-discover-89v49 1/1 Running 0 20h rook-discover-jdzhn 1/1 Running 0 20h rook-discover-sl9bv 1/1 Running 0 20h rook-discover-wg25w 1/1 Running 0 20h 2.4 增删osd 2.4.1 添加相关label kubectl label nodes 192.168.1.165 app.rook=storage kubectl label nodes 192.168.1.165 ceph-osd=enabled 2.4.2 修改cluster.yaml nodes: - name: "192.168.1.162" devices: - name: "nvme0n1p1" - name: "192.168.1.163" devices: - name: "nvme0n1p1" - name: "192.168.1.164" devices: - name: "nvme0n1p1" - name: "192.168.17.213" devices: - name: "nvme0n1p1" #添加165的磁盘信息 - name: "192.168.1.165" devices: - name: "nvme0n1p1" 2.4.3 apply cluster.yaml kubectl apply -f cluster.yaml 2.4.4 删除osd cluster.yaml去掉相关节点,再apply 2.5 安装dashboard 这是我自己的traefik ingress,yaml目录里有很多dashboard暴露方式,自行选择 dashboard已经在前述的步骤中包含了,这里只需要把dashboard service的服务暴露出来。有多种方法,我使用的是ingress的方式来暴露: apiVersion: traefik.containo.us/v1alpha1 kind: Ingre***oute metadata: name: traefik-ceph-dashboard annotations: kubernetes.io/ingress.class: traefik-v2.3 spec: entryPoints: - web routes: - match: Host(`ceph.foxchan.com`) kind: Rule services: - name: rook-ceph-mgr-dashboard namespace: rook-ceph port: 7000 middlewares: - name: gs-ipwhitelist 登录 dashboard 需要安全访问。Rook 在运行 Rook Ceph 集群的名称空间中创建一个默认用户,admin 并生成一个称为的秘密rook-ceph-dashboard-admin-password 要检索生成的密码,可以运行以下命令: kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo 2.6 安装toolbox 执行下面的命令: kubectl apply -f toolbox.yaml 成功后,可以使用下面的命令来确定toolbox的pod已经启动成功: kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" 然后可以使用下面的命令登录该pod,执行各种ceph命令: kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash 比如: ceph status ceph osd status ceph df rados df 删除toolbox kubectl -n rook-ceph delete deploy/rook-ceph-tools 2.7 prometheus监控 监控部署很简单,利用Prometheus Operator,独立部署一套prometheus 安装prometheus operator kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/v0.40.0/bundle.yaml 安装prometheus git clone --single-branch --branch v1.5.1 https://github.com/rook/rook.git cd rook/cluster/examples/kubernetes/ceph/monitoring kubectl create -f service-monitor.yaml kubectl create -f prometheus.yaml kubectl create -f prometheus-service.yaml 默认是nodeport方式暴露 echo "http://$(kubectl -n rook-ceph -o jsonpath={.status.hostIP} get pod prometheus-rook-prometheus-0):30900" 开启Prometheus Alerts 此操作必须在ceph集群安装之前 安装rbac kubectl create -f cluster/examples/kubernetes/ceph/monitoring/rbac.yaml 确保cluster.yaml 开启 apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph [...] spec: [...] monitoring: enabled: true rulesNamespace: "rook-ceph" [...] Grafana Dashboards Grafana 版本大于等于 7.2.0 推荐一下dashboard Ceph - Cluster Ceph - OSD (Single) Ceph - Pools 2.8 删除ceph集群 删除ceph集群前,请先清理相关pod 删除块存储和文件存储 kubectl delete -n rook-ceph cephblockpool replicapool kubectl delete storageclass rook-ceph-block kubectl delete -f csi/cephfs/filesystem.yaml kubectl delete storageclass csi-cephfs rook-ceph-block 删除operator和相关crd kubectl delete -f operator.yaml kubectl delete -f common.yaml kubectl delete -f crds.yaml 清除主机上的数据 删除Ceph集群后,在之前部署Ceph组件节点的/data/rook/目录,会遗留下Ceph集群的配置信息。 若之后再部署新的Ceph集群,先把之前Ceph集群的这些信息删除,不然启动monitor会失败; # cat clean-rook-dir.sh hosts=( 192.168.1.213 192.168.1.162 192.168.1.163 192.168.1.164 ) for host in ${hosts[@]} ; do ssh $host "rm -rf /data/rook/*" done 清除device #!/usr/bin/env bash DISK="/dev/nvme0n1p1" # Zap the disk to a fresh, usable state (zap-all is important, b/c MBR has to be clean) # You will have to run this step for all disks. sgdisk --zap-all $DISK # hdd 用以下命令 dd if=/dev/zero of="$DISK" bs=1M count=100 oflag=direct,dsync # ssd 用以下命令 blkdiscard $DISK # These steps only have to be run once on each node # If rook sets up osds using ceph-volume, teardown leaves some devices mapped that lock the disks. ls /dev/mapper/ceph-* | xargs -I% -- dmsetup remove % # ceph-volume setup can leave ceph-<UUID> directories in /dev (unnecessary clutter) rm -rf /dev/ceph-* 如果因为某些原因导致删除ceph集群卡主,可以先执行以下命令, 再删除ceph集群就不会卡主了 kubectl -n rook-ceph patch cephclusters.ceph.rook.io rook-ceph -p '{"metadata":{"finalizers": []}}' --type=merge 2.9 rook升级 2.9.1 小版本升级 Rook v1.5.0 to Rook v1.5.1 git clone --single-branch --branch v1.5.1 https://github.com/rook/rook.gits cd $YOUR_ROOK_REPO/cluster/examples/kubernetes/ceph/ kubectl apply -f common.yaml -f crds.yaml kubectl -n rook-ceph set image deploy/rook-ceph-operator rook-ceph-operator=rook/ceph:v1.5.1 2.9.2 跨版本升级 Rook v1.4.x to Rook v1.5.x. 准备 设置环境变量 # Parameterize the environment export ROOK_SYSTEM_NAMESPACE="rook-ceph" export ROOK_NAMESPACE="rook-ceph" 升级之前需要保证集群健康 所有pod 是running kubectl -n $ROOK_NAMESPACE get pods 通过tool 查看ceph集群状态是否正常 TOOLS_POD=$(kubectl -n $ROOK_NAMESPACE get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') kubectl -n $ROOK_NAMESPACE exec -it $TOOLS_POD -- ceph status cluster: id: 194d139f-17e7-4e9c-889d-2426a844c91b health: HEALTH_OK services: mon: 3 daemons, quorum a,b,c (age 25h) mgr: a(active, since 5h) mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay osd: 4 osds: 4 up (since 25h), 4 in (since 25h) task status: scrub status: mds.myfs-a: idle mds.myfs-b: idle data: pools: 4 pools, 97 pgs objects: 2.08k objects, 7.6 GiB usage: 26 GiB used, 3.3 TiB / 3.3 TiB avail pgs: 97 active+clean io: client: 1.2 KiB/s rd, 2 op/s rd, 0 op/s wr 升级operator 1、 升级common和crd git clone --single-branch --branch v1.5.1 https://github.com/rook/rook.gits cd rook/cluster/examples/kubernetes/ceph kubectl apply -f common.yaml -f crds.yaml 2、升级 Ceph CSI versions 可以修改cm来自己制定镜像版本,如果是默认的配置,无需修改 kubectl -n rook-ceph get configmap rook-ceph-operator-config ROOK_CSI_CEPH_IMAGE: "harbor.foxchan.com/google_containers/cephcsi/cephcsi:v3.1.1" ROOK_CSI_REGISTRAR_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-node-driver-registrar:v2.0.1" ROOK_CSI_PROVISIONER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-provisioner:v2.0.0" ROOK_CSI_SNAPSHOTTER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-snapshotter:v3.0.0" ROOK_CSI_ATTACHER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-attacher:v3.0.0" ROOK_CSI_RESIZER_IMAGE: "harbor.foxchan.com/google_containers/k8scsi/csi-resizer:v1.0.0" 3、升级 Rook Operator kubectl -n $ROOK_SYSTEM_NAMESPACE set image deploy/rook-ceph-operator rook-ceph-operator=rook/ceph:v1.5.1 4、等待集群 升级完毕 watch --exec kubectl -n $ROOK_NAMESPACE get deployments -l rook_cluster=$ROOK_NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name}{" \treq/upd/avl: "}{.spec.replicas}{"/"}{.status.updatedReplicas}{"/"}{.status.readyReplicas}{" \trook-version="}{.metadata.labels.rook-version}{"\n"}{end}' 5、验证集群升级完毕 kubectl -n $ROOK_NAMESPACE get deployment -l rook_cluster=$ROOK_NAMESPACE -o jsonpath='{range .items[*]}{"rook-version="}{.metadata.labels.rook-version}{"\n"}{end}' | sort | uniq 升级ceph 版本 如果集群状态不监控,operator会拒绝升级 1、升级ceph镜像 NEW_CEPH_IMAGE='ceph/ceph:v15.2.5' CLUSTER_NAME=rook-ceph kubectl -n rook-ceph patch CephCluster rook-ceph --type=merge -p "{\"spec\": {\"cephVersion\": {\"image\": \"$NEW_CEPH_IMAGE\"}}}" 2、观察pod 升级 watch --exec kubectl -n $ROOK_NAMESPACE get deployments -l rook_cluster=$ROOK_NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name}{" \treq/upd/avl: "}{.spec.replicas}{"/"}{.status.updatedReplicas}{"/"}{.status.readyReplicas}{" \tceph-version="}{.metadata.labels.ceph-version}{"\n"}{end}' 3、查看ceph集群是否正常 kubectl -n $ROOK_NAMESPACE get deployment -l rook_cluster=$ROOK_NAMESPACE -o jsonpath='{range .items[*]}{"ceph-version="}{.metadata.labels.ceph-version}{"\n"}{end}' | sort | uniq 三、部署块存储 3.1 创建pool和StorageClass # 定义一个块存储池 apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: replicapool namespace: rook-ceph spec: # 每个数据副本必须跨越不同的故障域分布,如果设置为host,则保证每个副本在不同机器上 failureDomain: host # 副本数量 replicated: size: 3 # Disallow setting pool with replica 1, this could lead to data loss without recovery. # Make sure you're *ABSOLUTELY CERTAIN* that is what you want requireSafeReplicaSize: true # gives a hint (%) to Ceph in terms of expected consumption of the total cluster capacity of a given pool # for more info: https://docs.ceph.com/docs/master/rados/operations/placement-groups/#specifying-expected-pool-size #targetSizeRatio: .5 --- # 定义一个StorageClass apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-ceph-block # 该SC的Provisioner标识,rook-ceph前缀即当前命名空间 provisioner: rook-ceph.rbd.csi.ceph.com parameters: # clusterID 就是集群所在的命名空间名 # If you change this namespace, also change the namespace below where the secret namespaces are defined clusterID: rook-ceph # If you want to use erasure coded pool with RBD, you need to create # two pools. one erasure coded and one replicated. # You need to specify the replicated pool here in the `pool` parameter, it is # used for the metadata of the images. # The erasure coded pool must be set as the `dataPool` parameter below. #dataPool: ec-data-pool # RBD镜像在哪个池中创建 pool: replicapool # RBD image format. Defaults to "2". imageFormat: "2" # 指定image特性,CSI RBD目前仅仅支持layering imageFeatures: layering # Ceph admin 管理凭证配置,由operator 自动生成 # in the same namespace as the cluster. csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph # 卷的文件系统类型,默认ext4,不建议xfs,因为存在潜在的死锁问题(超融合设置下卷被挂载到相同节点作为OSD时) csi.storage.k8s.io/fstype: ext4 # uncomment the following to use rbd-nbd as mounter on supported nodes # **IMPORTANT**: If you are using rbd-nbd as the mounter, during upgrade you will be hit a ceph-csi # issue that causes the mount to be disconnected. You will need to follow special upgrade steps # to restart your application pods. Therefore, this option is not recommended. #mounter: rbd-nbd allowVolumeExpansion: true reclaimPolicy: Delete 3.2 demo示例 推荐pvc 和应用写到一个yaml里面 #创建pvc apiVersion: v1 kind: PersistentVolumeClaim metadata: name: rbd-demo-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: rook-ceph-block --- apiVersion: apps/v1 kind: Deployment metadata: name: csirbd-demo-pod labels: test-cephrbd: "true" spec: replicas: 1 selector: matchLabels: test-cephrbd: "true" template: metadata: labels: test-cephrbd: "true" spec: containers: - name: web-server-rbd image: harbor.foxchan.com/sys/nginx:1.19.4-alpine volumeMounts: - name: mypvc mountPath: /usr/share/nginx/html volumes: - name: mypvc persistentVolumeClaim: claimName: rbd-demo-pvc readOnly: false 四、部署文件系统 4.1 创建CephFS CephFS的CSI驱动使用Quotas来强制应用PVC声明的大小,仅仅4.17+内核才能支持CephFS quotas。 如果内核不支持,而且你需要配额管理,配置Operator环境变量 CSI_FORCE_CEPHFS_KERNEL_CLIENT: false来启用FUSE客户端。 使用FUSE客户端时,升级Ceph集群时应用Pod会断开mount,需要重启才能再次使用PV。 apiVersion: ceph.rook.io/v1 kind: CephFilesystem metadata: name: myfs namespace: rook-ceph spec: # The metadata pool spec. Must use replication. metadataPool: replicated: size: 3 requireSafeReplicaSize: true parameters: # Inline compression mode for the data pool # Further reference: https://docs.ceph.com/docs/nautilus/rados/configuration/bluestore-config-ref/#inline-compression compression_mode: none # gives a hint (%) to Ceph in terms of expected consumption of the total cluster capacity of a given pool # for more info: https://docs.ceph.com/docs/master/rados/operations/placement-groups/#specifying-expected-pool-size #target_size_ratio: ".5" # The list of data pool specs. Can use replication or erasure coding. dataPools: - failureDomain: host replicated: size: 3 # Disallow setting pool with replica 1, this could lead to data loss without recovery. # Make sure you're *ABSOLUTELY CERTAIN* that is what you want requireSafeReplicaSize: true parameters: # Inline compression mode for the data pool # Further reference: https://docs.ceph.com/docs/nautilus/rados/configuration/bluestore-config-ref/#inline-compression compression_mode: none # gives a hint (%) to Ceph in terms of expected consumption of the total cluster capacity of a given pool # for more info: https://docs.ceph.com/docs/master/rados/operations/placement-groups/#specifying-expected-pool-size #target_size_ratio: ".5" # Whether to preserve filesystem after CephFilesystem CRD deletion preserveFilesystemOnDelete: true # The metadata service (mds) configuration metadataServer: # The number of active MDS instances activeCount: 1 # Whether each active MDS instance will have an active standby with a warm metadata cache for faster failover. # If false, standbys will be available, but will not have a warm cache. activeStandby: true # The affinity rules to apply to the mds deployment placement: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: app.storage operator: In values: - rook-ceph # topologySpreadConstraints: # tolerations: # - key: mds-node # operator: Exists # podAffinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: ceph-mds operator: In values: - enabled # topologyKey: kubernetes.io/hostname will place MDS across different hosts topologyKey: kubernetes.io/hostname preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: ceph-mds operator: In values: - enabled # topologyKey: */zone can be used to spread MDS across different AZ # Use <topologyKey: failure-domain.beta.kubernetes.io/zone> in k8s cluster if your cluster is v1.16 or lower # Use <topologyKey: topology.kubernetes.io/zone> in k8s cluster is v1.17 or upper topologyKey: topology.kubernetes.io/zone # A key/value list of annotations annotations: # key: value # A key/value list of labels labels: # key: value resources: # The requests and limits set here, allow the filesystem MDS Pod(s) to use half of one CPU core and 1 gigabyte of memory # limits: # cpu: "500m" # memory: "1024Mi" # requests: # cpu: "500m" # memory: "1024Mi" # priorityClassName: my-priority-class 4.2 创建StorageClass apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-cephfs provisioner: rook-ceph.cephfs.csi.ceph.com parameters: # clusterID is the namespace where operator is deployed. clusterID: rook-ceph # CephFS filesystem name into which the volume shall be created fsName: myfs # Ceph pool into which the volume shall be created # Required for provisionVolume: "true" pool: myfs-data0 # Root path of an existing CephFS volume # Required for provisionVolume: "false" # rootPath: /absolute/path # The secrets contain Ceph admin credentials. These are generated automatically by the operator # in the same namespace as the cluster. csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph # (optional) The driver can use either ceph-fuse (fuse) or ceph kernel client (kernel) # If omitted, default volume mounter will be used - this is determined by probing for ceph-fuse # or by setting the default mounter explicitly via --volumemounter command-line argument. #使用kernel client mounter: kernel reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: # uncomment the following line for debugging #- debug 4.3 创建pvc 在创建cephfs 的pvc 发现一直处于pending状态,社区有人认为是网络组件的差异,目前我的calico无法成功,只能改为host模式,flannel可以。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cephfs-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: rook-cephfs 4.4 demo示例 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cephfs-demo-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: rook-cephfs --- apiVersion: apps/v1 kind: Deployment metadata: name: csicephfs-demo-pod labels: test-cephfs: "true" spec: replicas: 2 selector: matchLabels: test-cephfs: "true" template: metadata: labels: test-cephfs: "true" spec: containers: - name: web-server image: harbor.foxchan.com/sys/nginx:1.19.4-alpine imagePullPolicy: Always volumeMounts: - name: mypvc mountPath: /usr/share/nginx/html volumes: - name: mypvc persistentVolumeClaim: claimName: cephfs-demo-pvc readOnly: false 五、遇到问题 5.1 lvm direct 不能直接做osd 存储 官方issue https://github.com/rook/rook/issues/5751 https://github.com/rook/rook/issues/2047 解决方式: 可以手动创建本地pvc,把lvm挂载上在做osd设备。如果手动闲麻烦,可以使用local-path-provisioner 5.2 Cephfs pvc pending 官方issue https://github.com/rook/rook/issues/6183 https://github.com/rook/rook/issues/4006 解决方式: 更换k8s 网络组件,或者把ceph集群网络开启host

优秀的个人博客,低调大师

HBase实操 | 如何使用HBase存储图片

1.文档编写目的 Fayson在前面的文章中介绍了《如何使用HBase存储文本文件》和《如何使用Lily HBase Indexer对HBase中的数据在Solr中建立索引》,实现了文本文件保存到HBase中,并基于Solr实现了文本文件的全文检索。如果我们碰到的是图片文件呢,该如何保存或存储呢。本文主要描述如何将图片文件转成sequence file,然后保存到HBase。 内容概述 1.文件处理流程 2.准备上传文件的Java代码 3.运行代码 4.Hue中查询验证 测试环境 1.RedHat7.4 2.CM5.14.3 3.CDH5.14.2 4.集群未启用Kerberos 2.图片处理流程 1.如上图所示,Fayson先在本地准备了一堆图片文件,并上传到HDFS。 上传到HDFS 2.然后通过Java程序遍历所有图片生成一个Sequence File,

优秀的个人博客,低调大师

【实操】快速搭建常规数据库

阿里云有提供高可用的数据库产品RDS,但用户出于使用习惯或使用场景的考虑,会考虑自建数据库,本文介绍如何在云服务器ECS实例上快速搭建常用数据库。 如果还没有购买服务器,可以直接在购买时进行搭建工作。1.首先登录云服务器管理控制台。2.选择 云服务器 > 创建实例。在创建实例的页面上,选好地域配置等,然后定位到镜像,单击 镜像市场。3.点击镜像市场的 从镜像市场选择(含操作系统),弹出如下窗口。 在窗口中可选择相应的分类,或直接搜索出想要的镜像。 点击右侧使用,然后继续设置ECS的系统盘,安全组等设置,最后提交订单。如需要正常使用,还需要在ECS所属的安全组配置入方向的开放1521、1158端口,可参见之前发出的《阿里云:安全组规则配置》。 如果已经购买,则可通过更换系统盘来实现,可参见之前发出的《阿里云:更换系统盘》,在选择镜像时选择镜像市场中的镜像,同样需要用户开放1521、1158端口。 以上就是全部内容了,如果大家在操作中遇到问题,可以在下方留言与我们进行交流。 想获得更多信息,请扫描二维码,关注云特快。如您有疑问也可通过公众号或者直接来电400-650-2029与资深专家进行一对一沟通解决。

优秀的个人博客,低调大师

【实操】如何安装及查看云监控

大家好,本期为大家介绍如何安装及查看云监控。云监控是阿里云多年来服务器监控技术研究积累的成果,结合阿里云云计算平台强大的数据分析能力,为您提供云服务监控、站点监控和自定义监控,为您云上的产品、业务保驾护航。 下面开始演示:首先登录控制台,点击左侧的云服务器ECS,选择实例进入实例详情。可以看到右侧的监控信息,这里可以看到服务器的CPU使用率和内网的流量。点击查看内存等更多指标。这里可以看到CPU、内存、磁盘的使用情况和网络的运行状况。阿里云为用户提供了最短1小时,最长14天的查看方式,还可以选择时间范围。点击图片的右上角还可以查看大图或者切换其它指标。不但可以监控操作系统和基础硬件产品,还可以监控进程。如果大家在打开云监控界面后看不到相关的监控的信息说明实例没有安装云监控插件。我们可以点击左侧的主机监控,这里可以看到实例的插件状态。我们点击新购ECS自动安装云监控后面的开关把它打开,然后点击确定。以后新创建的ECS实例都会自动安装插件。也可以选择实例,点击下方的批量安装插件可以让系统自动安装插件。不过这些方法有时会安装不成功。如果安装失败就需要我们进行手动安装,点击上方的阿里云主机手工安装。有经典版监控插件和高性能监控插件供我们选择。然后选择主机类型和地域,最后选择操作系统。下面就可以看到安装命令了,Windows系统则需要我们自行下载插件去安装。 以上就是本期云监控的全部内容,如在操作时还遇到其他问题,也可给我们留言,我们会一一为大家解答,谢谢大家观看。 想获得更多信息,请扫描二维码,关注云特快。如您有疑问也可通过公众号或者直接来电400-650-2029与资深专家进行一对一沟通解决。

优秀的个人博客,低调大师

【视频】实操更换系统盘

大家好,本期视频给大家介绍如何更换阿里云服务器的系统盘。当业务发生变化需要我们变更服务器操作系统的时候,或是随着业务不断的发展,原有磁盘空间不能满足业务需求。需要扩容系统盘的时候就需要我们来通过更换系统盘的方式解决。 如在操作时还遇到其他问题,也可给我们留言,我们会一一为大家解答,谢谢大家观看。 想获得更多信息,请扫描二维码,关注云特快。如您有疑问也可通过公众号或者直接来电400-650-2029与资深专家进行一对一沟通解决。

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册