自v1.4.2起,ProxySQL支持本机群集。这意味着多个ProxySQL实例可识别群集; 他们了解彼此的状态,并能够通过根据配置版本,时间戳和校验和值同步最新的配置来自动处理配置更改。

ProxySQL是一个分散的代理,建议更靠近应用程序部署。这种方法甚至可以扩展到数百个节点,因为它可以在运行时轻松重新配置。为了有效地管理多个ProxySQL节点,必须确保在其中一个节点上执行的任何更改都应该应用于服务器场中的所有节点。如果没有本机群集,则必须手动导出配置并将其导入其他节点(尽管您可以自行进行自动化)。

使用ConfigMap中的集中配置方法,这种方法或多或少非常有效。无论加载到ConfigMap中的是什么都将被安装到pod中。更新配置可以通过版本控制(修改proxysql.cnf内容并将其加载到另一个名称的ConfigMap),然后根据部署方法调度和更新策略推送到pod。

但是,在快速变化的环境中,这种ConfigMap方法可能不是最好的方法,因为为了加载新配置,需要重新安排pod重新安排ConfigMap卷,这可能会危及整个ProxySQL服务。例如,假设在我们的环境中,我们的严格密码策略要求每7天强制MySQL用户密码过期,我们必须每周更新ProxySQL ConfigMap以获取新密码。另外,ProxySQL中的MySQL用户需要用户和密码才能匹配后端MySQL服务器上的用户和密码。这就是我们应该开始在Kubernetes中使用ProxySQL本机群集支持的地方,自动应用配置更改,而无需ConfigMap版本控制和pod重新安排的麻烦。

在这篇博文中,我将向您展示如何在Kubernetes上运行具有无头服务的ProxySQL本机群集。我们的高级架构可以说明如下:

我们在ClusterControl部署和管理的裸机基础设施上运行了3个Galera节点:

  • 192.168.0.21
  • 192.168.0.22
  • 192.168.0.23

我们的应用程序都在Kubernetes中作为pod运行。我们的想法是在应用程序和数据库集群之间引入两个ProxySQL实例作为反向代理。然后,应用程序将通过Kubernetes服务连接到ProxySQL pod,这将在多个ProxySQL副本之间进行负载平衡和故障转移。

以下是我们的Kubernetes设置的摘要:

1
2
3
4
5
root@kube1:~# kubectl get nodes -o wide<font></font>
NAME    STATUS   ROLES    AGE     VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME<font></font>
kube1   Ready    master   5m      v1.15.1   192.168.100.201   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7<font></font>
kube2   Ready    <none>   4m1s    v1.15.1   192.168.100.202   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7<font></font>
kube3   Ready    <none>   3m42s   v1.15.1   192.168.100.203   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7

通过ConfigMap进行ProxySQL配置

让我们首先准备我们的基本配置,它将被加载到ConfigMap中。创建一个名为proxysql.cnf的文件并添加以下行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
datadir="/var/lib/proxysql"<font></font>
<font></font>
admin_variables=<font></font>
{<font></font>
    admin_credentials="proxysql-admin:adminpassw0rd;cluster1:secret1pass"<font></font>
    mysql_ifaces="0.0.0.0:6032"<font></font>
    refresh_interval=2000<font></font>
    cluster_username="cluster1"<font></font>
    cluster_password="secret1pass"<font></font>
    cluster_check_interval_ms=200<font></font>
    cluster_check_status_frequency=100<font></font>
    cluster_mysql_query_rules_save_to_disk=true<font></font>
    cluster_mysql_servers_save_to_disk=true<font></font>
    cluster_mysql_users_save_to_disk=true<font></font>
    cluster_proxysql_servers_save_to_disk=true<font></font>
    cluster_mysql_query_rules_diffs_before_sync=3<font></font>
    cluster_mysql_servers_diffs_before_sync=3<font></font>
    cluster_mysql_users_diffs_before_sync=3<font></font>
    cluster_proxysql_servers_diffs_before_sync=3<font></font>
}<font></font>
<font></font>
mysql_variables=<font></font>
{<font></font>
    threads=4<font></font>
    max_connections=2048<font></font>
    default_query_delay=0<font></font>
    default_query_timeout=36000000<font></font>
    have_compress=true<font></font>
    poll_timeout=2000<font></font>
    interfaces="0.0.0.0:6033;/tmp/proxysql.sock"<font></font>
    default_schema="information_schema"<font></font>
    stacksize=1048576<font></font>
    server_version="5.1.30"<font></font>
    connect_timeout_server=10000<font></font>
    monitor_history=60000<font></font>
    monitor_connect_interval=200000<font></font>
    monitor_ping_interval=200000<font></font>
    ping_interval_server_msec=10000<font></font>
    ping_timeout_server=200<font></font>
    commands_stats=true<font></font>
    sessions_sort=true<font></font>
    monitor_username="proxysql"<font></font>
    monitor_password="proxysqlpassw0rd"<font></font>
    monitor_galera_healthcheck_interval=2000<font></font>
    monitor_galera_healthcheck_timeout=800<font></font>
}<font></font>
<font></font>
mysql_galera_hostgroups =<font></font>
(<font></font>
    {<font></font>
        writer_hostgroup=10<font></font>
        backup_writer_hostgroup=20<font></font>
        reader_hostgroup=30<font></font>
        offline_hostgroup=9999<font></font>
        max_writers=1<font></font>
        writer_is_also_reader=1<font></font>
        max_transactions_behind=30<font></font>
        active=1<font></font>
    }<font></font>
)<font></font>
<font></font>
mysql_servers =<font></font>
(<font></font>
    { address="192.168.0.21" , port=3306 , hostgroup=10, max_connections=100 },<font></font>
    { address="192.168.0.22" , port=3306 , hostgroup=10, max_connections=100 },<font></font>
    { address="192.168.0.23" , port=3306 , hostgroup=10, max_connections=100 }<font></font>
)<font></font>
<font></font>
mysql_query_rules =<font></font>
(<font></font>
    {<font></font>
        rule_id=100<font></font>
        active=1<font></font>
        match_pattern="^SELECT .* FOR UPDATE"<font></font>
        destination_hostgroup=10<font></font>
        apply=1<font></font>
    },<font></font>
    {<font></font>
        rule_id=200<font></font>
        active=1<font></font>
        match_pattern="^SELECT .*"<font></font>
        destination_hostgroup=20<font></font>
        apply=1<font></font>
    },<font></font>
    {<font></font>
        rule_id=300<font></font>
        active=1<font></font>
        match_pattern=".*"<font></font>
        destination_hostgroup=10<font></font>
        apply=1<font></font>
    }<font></font>
)<font></font>
<font></font>
mysql_users =<font></font>
(<font></font>
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },<font></font>
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }<font></font>
)<font></font>
<font></font>
proxysql_servers =<font></font>
(<font></font>
    { hostname = "proxysql-0.proxysqlcluster", port = 6032, weight = 1 },<font></font>
    { hostname = "proxysql-1.proxysqlcluster", port = 6032, weight = 1 }<font></font>
)

以下部分解释了上面的一些配置行:

admin_variables

注意admin_credentials变量,我们使用非默认用户“proxysql-admin”。ProxySQL仅通过localhost为本地连接保留默认的“admin”用户。因此,我们必须使用其他用户远程访问ProxySQL实例。否则,您将收到以下错误:

 
1
ERROR 1040 (42000): User 'admin' can only connect locally

我们还在admin_credentials行中附加了cluster_usernamecluster_password值,以分号分隔以允许自动同步发生。所有以cluster_ *为前缀的变量都与ProxySQL本机群集相关,并且不言自明。

mysql_galera_hostgroups

这是为ProxySQL 2.x引入的新指令(我们的ProxySQL映像在2.0.5上运行)。如果您想在ProxySQL 1.x上运行,请删除此部分并改为使用调度程序表。我们已经在这篇博文中解释了配置细节,如何在Docker上运行和配置针对MySQL Galera Cluster的ProxySQL 2.0“对Galera集群的 ProxySQL 2.x支持”。

mysql_servers

所有行都是不言自明的,它基于在MySQL Galera Cluster中运行的三个数据库服务器,如以下从ClusterControl获取的拓扑截图中所概述:

proxysql_servers

这里我们定义一个ProxySQL对等列表:

  • hostname - 对等方的主机名/ IP地址
  • port - Peer的管理端口
  • 重量 - 目前未使用,但在未来增强的路线图中
  • 评论 - 免费表单评论字段

在Docker / Kubernetes环境中,有多种方法可以发现和链接容器主机名或IP地址,并将它们插入到此表中,方法是使用ConfigMap,手动插入,通过entrypoint.sh脚本,环境变量或其他方法。在Kubernetes中,根据所使用的ReplicationController或Deployment方法,在高级中猜测pod的可解析主机名有点棘手,除非您在StatefulSet上运行。

查看有关StatefulState pod序数索引的本教程,该索引为创建的pod提供稳定的可解析主机名。将此与无头服务相结合(进一步解释),可解析的主机名格式为:

{APP_NAME} - {index_number} {}服务。

其中{service}是无头服务,它解释了“proxysql-0.proxysqlcluster”和“proxysql-1.proxysqlcluster”的来源。如果要包含2个以上的副本,请通过附加相对于StatefulSet应用程序名称的升序索引号来相应地添加更多条目。

现在我们准备将配置文件推送到ConfigMap,它将在部署期间安装到每个ProxySQL pod中:

1
$ kubectl create configmap proxysql-configmap --from-file=proxysql.cnf

验证我们的ConfigMap是否正确加载:

1
2
3
$ kubectl get configmap<font></font>
NAME                 DATA   AGE<font></font>
proxysql-configmap   1      7h57m

创建ProxySQL监控用户

开始部署之前的下一步是在数据库集群中创建ProxySQL监控用户。由于我们在Galera集群上运行,因此在其中一个Galera节点上运行以下语句:

1
2
mysql> CREATE USER 'proxysql'@'%' IDENTIFIED BY 'proxysqlpassw0rd';<font></font>
mysql> GRANT USAGE ON *.* TO 'proxysql'@'%';

如果您还没有创建MySQL用户(如上面mysql_users部分所述),我们也必须创建它们:

1
2
3
4
mysql> CREATE USER 'wordpress'@'%' IDENTIFIED BY 'passw0rd';<font></font>
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%';<font></font>
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';<font></font>
mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'proxysql'@'%';

而已。我们现在准备开始部署。

部署StatefulSet

我们将首先使用StatefulSet为冗余目的创建两个ProxySQL实例或副本。

让我们首先创建一个名为proxysql-ss-svc.yml的文本文件,并添加以下行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
apiVersion: apps/v1<font></font>
kind: StatefulSet<font></font>
metadata:<font></font>
  name: proxysql<font></font>
  labels:<font></font>
    app: proxysql<font></font>
spec:<font></font>
  replicas: 2<font></font>
  serviceName: proxysqlcluster<font></font>
  selector:<font></font>
    matchLabels:<font></font>
      app: proxysql<font></font>
      tier: frontend<font></font>
  updateStrategy:<font></font>
    type: RollingUpdate<font></font>
  template:<font></font>
    metadata:<font></font>
      labels:<font></font>
        app: proxysql<font></font>
        tier: frontend<font></font>
    spec:<font></font>
      restartPolicy: Always<font></font>
      containers:<font></font>
      - image: severalnines/proxysql:2.0.4<font></font>
        name: proxysql<font></font>
        volumeMounts:<font></font>
        - name: proxysql-config<font></font>
          mountPath: /etc/proxysql.cnf<font></font>
          subPath: proxysql.cnf<font></font>
        ports:<font></font>
        - containerPort: 6033<font></font>
          name: proxysql-mysql<font></font>
        - containerPort: 6032<font></font>
          name: proxysql-admin<font></font>
      volumes:<font></font>
      - name: proxysql-config<font></font>
        configMap:<font></font>
          name: proxysql-configmap<font></font>
---<font></font>
apiVersion: v1<font></font>
kind: Service<font></font>
metadata:<font></font>
  annotations:<font></font>
  labels:<font></font>
    app: proxysql<font></font>
    tier: frontend<font></font>
  name: proxysql<font></font>
spec:<font></font>
  ports:<font></font>
  - name: proxysql-mysql<font></font>
    port: 6033<font></font>
    protocol: TCP<font></font>
    targetPort: 6033<font></font>
  - name: proxysql-admin<font></font>
    nodePort: 30032<font></font>
    port: 6032<font></font>
    protocol: TCP<font></font>
    targetPort: 6032<font></font>
  selector:<font></font>
    app: proxysql<font></font>
    tier: frontend<font></font>
  type: NodePort

上面定义有两个部分 - StatefulSet和Service。StatefulSet是从proxysql-configmap加载的pods或副本以及ConfigMap卷的挂载点的定义。下一节是服务定义,我们在其中定义如何为内部或外部网络公开和路由pod。

验证pod和服务状态:

1
2
3
4
5
6
7
8
$ kubectl get pods,svc<font></font>
NAME             READY   STATUS    RESTARTS   AGE<font></font>
pod/proxysql-0   1/1     Running   0          4m46s<font></font>
pod/proxysql-1   1/1     Running   0          2m59s<font></font>
<font></font>
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE<font></font>
service/kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP                         10h<font></font>
service/proxysql          NodePort    10.111.240.193   <none>        6033:30314/TCP,6032:30032/TCP   5m28s

如果你看一下pod的日志,你会发现我们被这个警告淹没了:

1
2
3
$ kubectl logs -f proxysql-0<font></font>
...<font></font>
2019-08-01 19:06:18 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)

以上只是意味着proxysql-0无法解析“proxysql-1.proxysqlcluster”并连接到它,这是预料之中的,因为我们还没有为代理SQL间通信所需的DNS记录创建无头服务。

Kubernetes无头服务

为了使ProxySQL pod能够解析预期的FQDN并直接连接到它,解析过程必须能够查找分配的目标pod IP地址而不是虚拟IP地址。这是无头服务进入画面的地方。通过设置“ clusterIP = None ” 创建无头服务时,不会配置负载平衡,也不会为此服务分配集群IP(虚拟IP)。仅自动配置DNS。当您为无头服务运行DNS查询时,您将获得pod IP地址的列表。

如果我们查找“proxysqlcluster”的无头服务DNS记录(在此示例中我们有3个ProxySQL实例),这就是它的样子:

1
2
3
4
$ host proxysqlcluster<font></font>
proxysqlcluster.default.svc.cluster.local has address 10.40.0.2<font></font>
proxysqlcluster.default.svc.cluster.local has address 10.40.0.3<font></font>
proxysqlcluster.default.svc.cluster.local has address 10.32.0.2

同时,以下输出显示名为“proxysql”的标准服务的DNS记录,该记录解析为clusterIP:

1
2
$ host proxysql<font></font>
proxysql.default.svc.cluster.local has address 10.110.38.154

要创建无头服务并将其附加到pod,必须在StatefulSet声明中定义ServiceName,并且Service定义必须具有“ clusterIP = None ”,如下所示。创建一个名为proxysql-headless-svc.yml的文本文件,并添加以下行:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1<font></font>
kind: Service<font></font>
metadata:<font></font>
  name: proxysqlcluster<font></font>
  labels:<font></font>
    app: proxysql<font></font>
spec:<font></font>
  clusterIP: None<font></font>
  ports:<font></font>
  - port: 6032<font></font>
    name: proxysql-admin<font></font>
  selector:<font></font>
    app: proxysql

创建无头服务:

1
$ kubectl create -f proxysql-headless-svc.yml

仅用于验证,此时,我们运行以下服务:

1
2
3
4
5
$ kubectl get svc<font></font>
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE<font></font>
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP                         8h<font></font>
proxysql          NodePort    10.110.38.154   <none>        6033:30200/TCP,6032:30032/TCP   23m<font></font>
proxysqlcluster   ClusterIP   None            <none>        6032/TCP                        4s

现在,查看我们的pod日志之一:

1
2
3
4
5
$ kubectl logs -f proxysql-0<font></font>
...<font></font>
2019-08-01 19:06:19 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)<font></font>
2019-08-01 19:06:19 [INFO] Cluster: detected a new checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032, version 1, epoch 1564686376, checksum 0x3FEC69A5C9D96848 . Not syncing yet ...<font></font>
2019-08-01 19:06:19 [INFO] Cluster: checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032 matches with local checksum 0x3FEC69A5C9D96848 , we won't sync.

您会注意到Cluster组件能够通过名为“proxysqlcluster”的无头服务从端口6032上的其他对等端proxysql-1.proxysqlcluster解析,连接和检测新的校验和。请注意,此服务仅在Kubernetes网络中公开端口6032,因此无法从外部访问。

此时,我们的部署现已完成。

连接到ProxySQL

有几种方法可以连接到ProxySQL服务。负载均衡的MySQL连接应从Kubernetes网络内发送到端口6033,如果客户端从外部网络连接,则使用端口30033。

要从外部网络连接到ProxySQL管理界面,我们可以连接到NodePort部分30032下定义的端口(192.168.100.203是主机kube3.local的主IP地址):

1
$ mysql -uproxysql-admin -padminpassw0rd -h192.168.100.203 -P30032

如果要从Kubernetes网络中的其他pod访问,请在端口6032上使用clusterIP 10.110.38.154(在“proxysql”服务下定义)。

然后根据需要执行ProxySQL配置更改并将其加载到运行时:

1
2
mysql> INSERT INTO mysql_users (username,password,default_hostgroup) VALUES ('newuser','passw0rd',10);<font></font>
mysql> LOAD MYSQL USERS TO RUNTIME;

您将注意到其中一个窗格中的以下行指示配置同步完成:

1
2
3
4
5
6
$ kubectl logs -f proxysql-0<font></font>
...<font></font>
2019-08-02 03:53:48 [INFO] Cluster: detected a peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027, diff_check 4. Own version: 1, epoch: 1564714803. Proceeding with remote sync<font></font>
2019-08-02 03:53:48 [INFO] Cluster: detected peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027<font></font>
2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 started<font></font>
2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 completed

请记住,只有在ProxySQL运行时中发生配置更改时才会发生自动同步。因此,在看到动作之前运行“ LOAD ... TO RUNTIME ”语句至关重要。不要忘记将ProxySQL更改保存到磁盘中以保持持久性:

1
mysql> SAVE MYSQL USERS TO DISK;

局限性

请注意,此设置存在限制,因为ProxySQL不支持将活动配置保存/导出到文本配置文件中,以后我们可以将其加载到ConfigMap中以保持持久性。有一个功能要求。同时,您可以手动将修改推送到ConfigMap。否则,如果意外删除了pod,则会丢失当前配置,因为新的pod将由ConfigMap中定义的任何内容引导。

特别感谢Sampath Kamineni,他引发了这篇博客文章的想法,并提供了有关用例和实现的见解。

欢迎关注公众号:“Java架构师学习”

你会喜欢的!

使用Kubernetes进行ProxySQL本机群集的更多相关文章

  1. kubernetes之node 宕机,pod驱离问题解决

    背景: 当node宕机时,希望该node节点上的pod能够快速疏散到其他节点,并提供服务.测试发现,要等待5分钟,上面的pod才会疏散. 网上介绍通过修改 /etc/kubernetes/manife ...

  2. ProxySQL Cluster 高可用集群环境部署记录

    ProxySQL在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数据并不能共通,在主实例上配置后,仍需要在备用节点上进行配置,对管理来说非常不方便.但是Proxy ...

  3. ProxySQL Cluster 高可用集群 + MySQL MGR环境部署 (多写模式) 部署记录

    文章转载自:https://blog.51cto.com/u_6215974/4937192 ProxySQL 在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数 ...

  4. ProxySQL+MGR实现读写分离和主节点故障无感知切换 - 完整操作记录

    前面的文章介绍了ProxySQL用法,这里说下ProxySQL中间件针对Mysql组复制模式实现读写分离以及主节点故障时能够自动切换到新的主节点,而应用对此过程无感知的功能.Mysql组复制(MGR) ...

  5. ProxySQL 配置详解及读写分离(+GTID)等功能说明 (完整篇)

    ProxySQL是灵活强大的MySQL代理层, 是一个能实实在在用在生产环境的MySQL中间件,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行 cache,支持动态加载配 ...

  6. kubernetes学习:CKA考试认证

    考点 CKA认证针对考核成为当业界的Kubernetes管理员所需的技能. CKA认证考试包括这些一般领域及其在考试中的权重: 应用程序生命周期管理 -  8% 安装.配置和验证 -  12% 核心概 ...

  7. Kubernetes Clusters

    1. 创建集群 Kubernetes集群  Kubernetes协调一个高可用的计算机集群,作为一个单独的单元来一起工作.有了这种抽象,在Kubernetes中你就可以将容器化的应用程序部署到集群中, ...

  8. Kubernetes 开船记-脚踏两只船:用 master 服务器镜像克隆出新集群

    自从2020年2月23日 园子全站登船 之后,我们一边感叹"不上船不知道,一上船吓一跳" -- kubernetes 比 docker swarm 强大太多,一边有一个杞人忧天的担 ...

  9. K8S概念理解

    Master 负责管理集群 负责协调集群中的所有活动,例如调度应用程序,维护应用程序的状态,扩展和更新应用程序. Worker节点是VM(虚拟机)或物理计算机,充当k8s集群中的工作计算机. 每个Wo ...

随机推荐

  1. DataSet、DataTable、DataView三者关系及DataView 常见用法

    DATASET   可以理解为是个数据库. DATATABLE  可以理解为是个数据表. DATAVIEW   可以理解为是表的视图. dataset 数据集合可以包含多个datatable,而dat ...

  2. PWN INTEGER OVERFLOW 整数溢出

    0x00      Preview Last few passage I didn't conclude some important points and a general direction o ...

  3. TP框架对数据库的操作

    1.添加数据       1.1添加一条数据 $user = new User; $user->name = 'thinkphp'; $user->email = 'thinkphp@qq ...

  4. js简单动画:匀速动画、缓动动画、多物体动画以及透明度动画

    主要实现以下几种简单的动画效果(其实原理基本相同): 1.匀速动画:物体的速度固定 2.缓动动画:物体速度逐渐变慢 3.多物体动画 4.透明度动画 效果实现: 1.匀速动画(以物体左右匀速运动为例) ...

  5. CSS类的操作

    CSS类的操作 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  6. 控制DIV移动

    键盘控制DIV移动 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  7. Scrum Meeting - 第七周【Alpha阶段】

    每日任务内容: 本次会议为第七次Scrum Meeting会议 本次会议项目经理召开时间为20:00,在北区男生宿舍楼召开,召开时长约10分钟,探讨了本周选课网站编写的后续工作. 小组成员 本周任务 ...

  8. git版本控制入门--码云

    1.下载git:https://git-scm.com/download   2.安装过程一直点下一步即可.   3.进入刚创建的文件夹     4.在此时登录码云,创建项目.项目名称最好与文件夹名称 ...

  9. Spring Boot 项目维护全局json数据

    1:概述 过去 我们在每一个方法中处理前端发过来的请求,需要自己构造请求数据,然后通过spring 提供的@ResponseBody 强制转为JSON数据吗,实际上出现了很多重复的代码,我么亦可以通过 ...

  10. Nlog配置

    初次使用nlog,里里外外找了好久,终于搞会了. 使用nlog建日志输出到txt文件.数据库.邮件 nlog配置,如图 码云dome