Code Monkey home page Code Monkey logo

nepaul.github.io's People

Contributors

nepaul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

wisdom99

nepaul.github.io's Issues

Hello, Weex!

Weex 是一套简单易用的跨平台开发方案,能以 web 的开发体验构建高性能、可扩展的 native 应用,为了做到这些,Weex 与 Vue 合作,使用 Vue 作为上层框架,并遵循 W3C 标准实现了统一的 JSEngine 和 DOM API,这样一来,你甚至可以使用其他框架驱动 Weex,打造三端一致的 native 应用。
— weex 官网

本文的主要目的是 帮助 WEB 开发者快速搭建 weex 开发环境,以下所有操作均基于 macOS Sierra 下进行(最好还是用 mac 开发,毕竟我们的需求是 跨平台,而且 mac 对 WEB 开发真的非常友好)。

资源

  • 官网教程、手册、参考、工具和服务,建议四部分都看一遍,内容不长。
  • github
  • weex-packwiki :weexpack 是新一代的weex应用工程和插件工程开发套件,是基于weex快速搭建应用原型的利器。它能够帮助开发者通过命令行创建weex应用工程和插件工程,快速打包 weex 应用并安装到手机运行,对于具有分享精神的开发者而言还能够创建weex插件模版并发布插件到weex应用市场。 使用weexpack 能够方便的在在weex工程和native工程中安装插件(官方说法)。
  • [非官方] 饿了么前端在知乎的专栏, weex 入坑指南:其他文章写得也很好,建议都读一遍。
  • [非官方] 知乎上的评价, 如何评价阿里无线前端发布的Weex? - 知乎:阿里还是在努力避免成为 Kissy 那样的悲剧,并且已经是 Apache 基金会项目了。

基础安装

### 利用 Homebrew 安装 node ###
$ brew install node
### 查看 node 及 npm 是否能正常工作 ###
$ node -v
$ npm -v
### 国内墙的原因,建议用淘宝的 cnpm(https://npm.taobao.org/) ###
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
### 以后可以直接用 cnpm 替代 npm 使用 ###
$ cnpm i [package-name]

### 安装 weex-toolkit(https://weex.apache.org/cn/guide/tools/toolkit.html), 已经集成了 weexpack ###
$ cnpm install -g weex-toolkit

iOS 平台

  • 安装 Xcode(AppStore),并且运行一次,使 Xcode 自动安装开发者工具和确认使用协议
  • 安装 Xcode 项目的类库管理工具 CocoaPods
    • 由于墙,建议首先将 gem source 切换回 ruby-china 的:gem sources --add http://gems.ruby-china.org/ --remove https://rubygems.org/
    • 安装 CocoaPods: sudo gem install cocoapods

Android 平台

  • 安装 Android SDK:直接安装 Android Studio,通过 Android Studio 只能安装 SDK
  • 配置 SDK 环境变量
 $ vim ~/.bash_profile
	###  文件中添加如下两行
   export ANDROID_HOME=/xxx/Library/Android/sdk
   export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools
### 使配置生效
$ source ~/.bash_profile
  • 可能会遇到的问题
    • 如果之前有安装过 android sdk,建议卸载,保证 adb 等版本的统一(我的系统之前就用 brew 安装过,卸载 brew uninstall --force android-platform-tools
    • 创建项目后,建议直接用 USB 连接真机调试
      • 用模拟器遇到了各种莫名奇妙的问题
      • 真机需要开启 开发者权限。
      • 可以用 adb devices 查看设备是否连接成功到 PC

创建项目

### 利用 weex-toolkit ###
$ weex create hello-weex
### 安装依赖 ###
$ cd hello-weex && cnpm i

### 添加 iOS 模板
$ weex add ios

### 添加 Android 模板
$ weex platform add android

### 添加 iOS 模板
$ weex platform add ios

运行

  • 运行 Android:weex run android ,会自动编译安装到真机
  • 运行 iOS:weex run ios,会自动启动模拟机,并且编译安装到模拟机
    • 可能遇到的错误:导入 WeexATSDK.h 错误,解决方案:修改 platforms/ios/Podfile 文件中的 pod 'weex-ATSDK', '0.0.1'pod 'ATSDK', '0.0.1'

Enjoy!

第一个 weex 项目就是这么简单的跑起来。
本文的 weex 项目代码已经托管到 github
目前正在基于 一个开放的 API 服务写一个跨平台应用,后续会继续分享。

InfluxDB 浅尝

该文基于 InfluxDB v0.12.2 。

InfluxDB 是一个 基于时间序列的 go 语言开源数据库。并且没有其他依赖,安装和使用都相当方便快速(例如在以前的 Druid 極速體驗 介绍的 Druid 就依赖 Zookeeper 和 HDFS 等,而且安装使用相对繁琐)。非常适用于记录 metrics, events 和 performing analytics 等, 比如很多公司内部的 运维监控平台 或者 很多基于时间序列的服务平台等。

InfluxDB是一个非常年轻的开源项目,并且维持周期更新。该公司(已经有融资)基于 InfluxDB 也配套做了其他一系列的 工具,并且提供了 云服务。懒得自己搭建的可以考虑直接采用。

本文只是一个抛砖引玉。官方文档 非常写得既简单又翔实,建议大家好好阅读。

安装

网络

InfluxDB 默认需要以下两个端口(非本机使用需要注意在防火墙开通):

  • TCP 端口 8083,用于 管理界面
  • TCP 端口 8086, 用于 client 和 server 通过 HTTP API 进行通信

安装

InfluxDB 的安装和更新 非常非常方便!!! 支持众多平台:Ubuntu & Debian, RedHat & CentOS, SLES & openSUSE, FreeBSD/PC-BSD, Mac OS X.

以下以 RedHat & CentOS 为例,说明又多么方便。

第一步,配置 yum 包管理工具:

cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo
[influxdb]
name = InfluxDB Repository - RHEL \$releasever
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF

第二部,通过 yum 命令安装和启动:

sudo yum install influxdb
sudo service influxdb start

就是这么简单,单结点的 InfluxDB 已经安装启动完毕,可以直接使用了。

数据写入和查询

数据的写入和查询都是基于 HTTP API,也提供了很多主流语言的 HTTP API 客户端库

InfluxDB 也提供了一套 数据采样(Downsampling, 主要通过 CQ 方式实现) 和 数据保留(Data Retention)。可以在数据量很大的时候考虑采用,当然在任何必要的时候也可以使用。

InfluxDB 主要对硬盘的要求比较高,推荐直接使用 SSD。官方 也有针对 CPU, RAM, 和 IOPS 的一些配置建议。

写入

可以通过 HTTP API 写入实时数据,也可从文件导入数据。
其他的方式:

  • UDP: 需要在配置文件 (centos 下在 /etc/influxdb.conf) 中进行配置
  • Graphite
  • CollectD
  • OpenTSDB

查询

丰富的 SQL,支持SELECT WHERE GROUP BY LIMIT ORDER BY OFFSET 等等。

查询函数

Aggregations Selectors Transformations
COUNT() BOTTOM() CEILING()
DISTINCT() FIRST() DERIVATIVE()
INTEGRAL() LAST() DIFFERENCE()
MEAN() MAX() FLOOR()
MEDIAN() MIN() HISTOGRAM()
SPREAD() PERCENTILE() MOVING_AVERAGE()
SUM() TOP() NON_NEGATIVE_DERIVATIVE()
STDDEV()

高可用

虽然 InfluxDB 还是一个非常年轻的项目,但是已经有一套比较可靠的高可用方案了 —— Relay(一如既往得简单实用,不多说还是直接看官方文档吧)。

其他

资料

InfluxDB 的官方文档已经很详细,一般不会碰到太大的问题。
另外,官方博客也有很多干货,可以帮助我们更好地了解 InfluxDB 的使用。

性能

官方号称能够支持 千万级 的数据写入和查询。
我们在使用时,只是用了普通的机械硬盘和 8G 内存 的 CentOS 虚拟机。当时在的版本是 0.9.x,在数据量存到 10万后查询和写入都很慢了。以后考虑按照 官方配置 进行一下详细的实测。

30 分钟了解 AngularJS 的 Directive 方法

Directive: 简单来说就是在特定 DOM 元素上运行的函数,可以扩展该 DOM 元素的功能。

angular.module('myApp', [])
  .directive('myDirective', function() {
	  return {
      restrict: String,
		priority: Number,
		terminal: Boolean,
		template: String or Template Function,
		templateUrl: String,
		scope: Boolean or Object,
		transclude: Boolean,
		controller: String or Function,
		controllerAs: String,
		require: String,
		link: Function,
		compile: Function(返回一个对象或链接函数)
    }
});

restrict(字符串)

  • 可选,默认值为 A(属性)。在编译 HTML 时指定用哪种声明格式匹配指令定义,可以指定以元素(E)、属性(A)、类(C)或注释(M)的格式来调用指令。
  • 最佳实践
    1. 组件化的结构下,使用 元素(E)的方式会使代码更清晰易读。大部分自定义的指令应该是使用这种方式。(angular1.5 以上版本的 component 只支持元素(E)的方式)。
    2. 如果是重新声明一个已经存在的元素推荐使用 属性(A)的方式。
    3. 避免使用 类 或 注释的格式来调用指令。

priority(数值)

  • 可选,默认值为 0(例如 ngRepeat 为 1000, 最高优先级)。多个指令作用于同一个 HTML 元素时,用来指定优先级。
  • 具有更高优先级的指令优先运行
  • 若一个元素有两个相同优先级的指令,先声明的先运行

terminal(布尔)

  • 可选, 默认为 false。
  • 多个元素作用于同一个 HTML 元素时,用于停止运行比本指令优先级低的指令。

template(字符串或函数)

templateUrl(字符串或函数)

  • 可选:1. 一个代表外部 HTML 路径的字符串;2. 一个可以接受两个参数(tElement 和 tAttrs)的函数,该函数返回一个外部 HTML 路径的字符串
  • 通过 Ajax 异步加载 HTML 模板文件
  • 最佳实践
    1. 一般情况下建议使用该参数而避免使用 template,除非 template 非常非常小
    2. 模板加载后会将其默认缓存到 $templateCache 服务中。建议在生产环境中提前将模板缓存到一个定义模板的 JS 文件中,可以大大提高性能

replace(布尔)

  • 可选,默认为 false。默认即将模板当作子元素插入到调用此指令元素内部

scope(布尔或对象)

  • 隔离作用域。可选,默认值为 false(不创建子作用域,使用父作用域)。
  • 设置 scope 为 true 后,会从父作用域继承并创建一个新作用域对象。比如内置指令 ng-controller 就是用来创建一个从父作用域继承来的子作用域。
  • 隔离作用域
    1. 将 scope 设置为空对象 {},指令模板将无法访问外部作用域
    2. 使用场景:创建可复用的组件。避免组件在未知上下文使用时作用域相互污染
  • 绑定策略:三种将指令内部隔离作用域与外部作用进行数据绑定的方法
    1. @ (or @attr):绑定字符串
    2. = (or =attr): 双向绑定
    3. < (or <attr):单向绑定,只读
    4. & (or &attr):通过表达式的方式调用所在作用域的函数,但不能使用 {{}}

transclude ?

  • 可选,默认值为 false
  • 使用场景:通常用于常见可复用组件,典型例子是模态对话框或导航栏
  • 最佳实践:当希望创建一个可以包含任意内容的指令时,才使用 transclude: true

controller(字符串或函数)

controllerAs(子符串)

require(字符串或数组)

link(函数)

  • 创建操作 DOM 的指令。可选。
  • 函数标签:function link(scope, element, attrs, controller, transcludeFn) { ... }
    • scope:Angular scope 对象
    • element:使用此指令的元素
    • attr:定义在元素上的属性的 key-value 对象
    • controller:
    • transcluedFn:

compile(对象或函数)

其他最佳实践

  1. Directives 在使用后必须用 element.on(‘$destroy’, …) 或者 scope.$on(‘$destroy’, ...)做好清理工作,以免造成内存泄漏

内置指令

所有以 ng 开头的都是 AngularJS 提供的内置指令。
最佳实践:不要将自己的指令以 ng 开头。

基础 ng 属性指令

ng-href ng-disabled ng-readonly ng-selected ng-checked ng-href ng-src

  • 命名方式:在原生 HTML 属性前加了 ng。
  • 布尔属性 指令: ng-href ng-disabled ng-readonly ng-selected ng-checked
  • 类布尔属性 指令:ng-hrefng-src最佳实践:强烈建议在动态创建 href 和 src 属性时使用,因为它们会告诉浏览器在相应表达式生效之前不要执行相应操作。

在指令中使用 子作用域

  • ng-app ng-controller
  • 内置模板语法 {{}} ng-bind ng-bind-template ng-cloak
  • ng-if ng-show/ng-hide
  • ng-init
  • ng-repeat ng-model
  • ng-form ng-change ng-click
  • ng-switch ng-switch-when on=“propertyName”
  • ng-include ng-view

参考链接

规范

  1. 👍项目规范:Git, 文档,环境,npm 依赖,测试,工程结构和命名,代码风格,日志,API设计。言简意赅,切中要害!

MySQL 高可用实践

基于 MySQL5.7, Semisynchronous Replication(MySQL 半同步复制), Keepalived, MHA 的 MySQL 高可用方案

MySQL, 用得最多最广泛的关系型数据库。 在生产环境中,难免遇到诸如 需要重启服务器或者 MySQL 服务莫名宕了 等问题。如何保证 MySQL 能够持续提供读写等服务,即 高可用性?

本文主要讲述如何从无到有构建一套简单的 MySQL 高可用方案,少概念原理,多实操。

概念及架构简介

  • semi-synchronous Replication: 传统的 asynchronous 模式在 master 宕机时仍然有数据丢失的风险。MySQL5.5 之后提供了 semi-synchronous 模式,它会在 master 处理完一个事务并且等待至少一个支持 semi-synchronous 的 slave 确认收到该事件并将其写 入relay-log 之后才会返回。相较于前者,数据安全性更高。性能也无需担心,因为 facebook 也用了。
  • Keepalived: 基于 VRRP 实现的路由管理工具,在 负载均衡 和 高可用 场景中应用广泛。这里主要用来创建 VIP(虚拟路由)
  • MHA: 即 mysql-master-ha, 最主要的一个功能是监控 MySQL 主从集群( 确切地说主要监控 Master), 在 Master 出现故障后自动选择一个 Slave 提升为 Master,并且可以保证新 Master 和 Slave 的一致性。

来看一下 架构图

应用通过 VIP(虚拟路由,由 Keepalived 创建)访问 MySQL 集群。一主(图 M )二从(图 S1 和 S2),S2 作备用主库。一旦原 Master 节点出现故障,MHA 自动将主库切换到 S1,并且 S2 随之连接到新的 Master。MHA 同时通过 master_ip_failover_script 脚本停止原 Master 节点上的 Keepalived,路由自动切换到 新 Master。这时候外部应用实际访问的是 S1 了,不会出现 MySQL 突然无法使用的问题。

mysql-mha

机器规划

Host IP VIP Role Software
M 10.20.78.241 10.20.78.11 Master MySQL5.7 Keepalived MHA-Node
S1 10.20.78.243 备用 candidate_master (Slave) MySQL5.7 Keepalived MHA-Node
S2 10.20.78.245 - Slave MySQL5.7 MHA-Node
MHA-Manager 10.20.78.227 - MHA Manager MHA-Node MHA-Manger

M 出现故障后:

Host IP VIP Role
M 10.20.78.241 - stoped
S1 10.20.78.243 10.20.78.11 master
S2 10.20.78.245 - Slave
MHA-Manager 10.20.78.227 - MHA Manager(stoped)

集群的搭建

整个集群搭建安装分为 MySQL 半同步复制、MHA 和 VIP(Keepalived) 三大部分。几乎都是以命令的方式来展示。

在安装具体的软件之前,对所有机器 yum -y upgrade (这是一个很好的习惯)。

所有服务器上 安装 EPEL( MHA 依赖包需要):rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm

下面开始分别从 MySQL 的半同步复制、Keepalived(VIP) 和 MHA 三方面具体说明。

Semisynchronous Replication

MySQL 在 5.5 以上的版本支持 半同步 复制,并且需要已经配置好 主从复制。

安装 MySQL 5.7

// 安装
wget http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
yum localinstall mysql57-community-release-el6-7.noarch.rpm

// 检查是否安装成功
service mysqld start
service mysqld status
mysql --version

// 初始的安全配置
grep 'temporary password' /var/log/mysqld.log
mysql_secure_installation //根据提示操作, 包括设置 root 新密码等操作

// 开始使用
mysql -uroot -p

配置 MySQL 主从同步

Master 机器上的操作:

  • 修改 my.cnf

    [mysqld]
    server-id=1     ## 在整个 MySQL 集群中必须唯一
    log-bin=mysql-bin
    binlog_format=ROW
    
  • 重启服务:service mysqld restart

  • 创建 slave 同步需要的用户: mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_username'@'10.20.%.%' IDENTIFIED BY 'repl_password';

  • 查看 master 状态:mysql> show master status\G

Slave 机器上的操作:

  • 修改 my.cnf:

    [mysqld]
    server-id=2         
        log-bin=mysql-bin            // 只需要在 S1 节点上加入这个配置,因为该节点是作为 MySQL Master 的备机
    relay_log=relay-log
    skip-slave-start
    
  • 重启 mysql: service mysqld restart

  • S1(因为是作主备) 上创建 slave 同步需要的用户: mysql> GRANT REPLICATION SLAVE ON . TO 'repl_username'@'10.20.%.%' IDENTIFIED BY 'repl_password';

  • S2 上创建一个用户方便后期 mha-manager 操作 GRANT ALL PRIVILEGES ON *.* TO 'repl_username'@'10.20.%.%' IDENTIFIED BY 'repl_password';

  • 配置 Master 信息:
    mysql> CHANGE MASTER TO MASTER_HOST='10.20.78.241',MASTER_PORT=3306,MASTER_USER='mha',MASTER_PASSWORD='King@123',MASTER_LOG_FILE='mysql-bin.000009',MASTER_LOG_POS=496;

  • 启动 slave 并 查看状态

    mysql> START SLAVE  
    mysql> SHOW SLAVE STATUS\G
    

主从同步配置完成,检查状态

  • 回到 Master 机器,查看 slave 连接情况:mysql> show slave hosts;
  • Master 上创建数据库 mysql> CREATE DATABASE sync_test;,在两个 Slave 上查看,发现同步成功。

半同步

  • Master

    // 动态加载插件
    mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; 
    mysql> SET GLOBAL rpl_semi_sync_master_enabled = {0|1}; // 1 开启
    mysql> SET GLOBAL rpl_semi_sync_master_timeout = N; // 单位是 ms
    
  • Slave

    // 动态加载插件
    mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';   
    mysql> SET GLOBAL rpl_semi_sync_slave_enabled = {0|1}; / 1 开启
    mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
    
  • 半同步状态监控

    可以分别在 Master 和 Slave 上查看
    查看配置:`SHOW VARIABLES LIKE 'rpl_semi_sync%';`
    查看状态:`SHOW STATUS LIKE 'Rpl_semi_sync%';`
    

Keepalived

需要在 M 和 S1 两台服务器上安装配置

  • 安装, 最后一行编辑的 keepalived.conf 在这里

    wget http://www.keepalived.org/software/keepalived-1.2.20.tar.gz
    tar -zxvf keepalived-1.2.20.tar.gz 
    cd keepalived-1.2.20
     ./configure --prefix=/usr/local/keepalived
    make && make install
    cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived
    cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
    cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
    mkdir -p /etc/keepalived/
    cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf
    vim /etc/keepalived/keepalived.conf
    
  • 启动 keeplived: service keepalived start

  • 查看虚拟 IP: ip a,此时可以看到在 M 上虚拟 IP 挂载成功,S1 上没有该 IP。一旦 M 上的 keeplived 服务挂掉,虚拟 IP 自动挂载到 S1 上。

    若没有挂载成功,可查看默认 日志文件:/var/log/message

  • 给 MySQl 可操作 Keepalived 启停的权限

    通过 visudo 命令,在 /etc/sudoers 文件末尾添加如下几行:

    #mysql sudo keepalived
    Host_Alias HOSTKEEP =110.20.78.241 # 本机IP
    Cmnd_Alias COMKEEP = /etc/init.d/keepalived stop, /etc/init.d/keepalived start, /etc/init.d/keepalived restart, /etc/init.d/keepalived reload ## reload is used to check connection error
    User_Alias USERKEEP = mysql
    USERKEEP  HOSTKEEP=(ALL)  NOPASSWD:COMKEEP
    
    #Defaults   requiretty # 注释掉
    

MHA

MHA 由 Node 和 Manager 两部分组成,Node 安装在每一台 MySQL 服务器上,而 MHA-Manager 需要同时安装 Node 和 Manager.

三台 MySQL 服务上创建 MHA-Manger 需要的用户

CREATE USER 'mha_manager'@'172.16.%.%' IDENTIFIED BY 'Crasheye+!@#123';
GRANT ALL ON *.* TO 'mha_manager'@'172.16.%.%';

各节点间的SSH 公钥免密码登陆

MHA Manager 使用 SSH 连接到各个 MySQL 服务器,最新 Slave 节点上的MHA Node 也要用 SSH (scp) 把 relay log 文件发给各个从库节点

MHA 安装

三台 MySQL 服务器上安装 MHA-Node
yum install perl-DBD-MySQL -y
rpm -Uvh https://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.52-0.noarch.rpm  #需翻墙
MHA-Manager 结点
  • MHA-Manager 的安装

    yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager
    rpm -Uvh https://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.52-0.noarch.rpm
    rpm -Uvh https://mysql-master-ha.googlecode.com/files/mha4mysql-manager-0.52-0.noarch.rpm
    
  • 配置 /etc/mha/mha.conf(具体查看这里)

  • 编辑 master_ip_failover 脚本:/usr/local/mha/master_ip_failover

    主要作用是 kill 原 Master 服务器上的 Keeplived,核心代码如下(这里有完整可用的代码)

    my $vip = '10.20.78.11';
    my $ssh_start_vip = "/etc/init.d/keepalived start";
    my $ssh_stop_vip = "/etc/init.d/keepalived stop";
    
  • 检查节点间的 ssh 连接: masterha_check_ssh --conf=/etc/mha/mha.conf

    成功会在终端输出 「All SSH connection tests passed successfully」

  • 检查MySQL 主从同步: masterha_check_repl --conf=/etc/mha/mha.conf

    成功会在终端输出 MySQL Replication Health is OK.

  • 启动 MHA Manager: masterha_manager --conf=/etc/mha/mha.conf

  • 查看 MHA 状态 masterha_check_status --conf=/etc/mha/mha.conf

    正常显 「PING_OK」,否则显示 「NOT_RUNNING」

全部配置完毕,enjoy it!

Fail-Over 及 故障恢复

FAQ

  1. 配置 ssh 免密码登陆

    Q: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

    A: 查看 ssh 配置文件(vim /etc/ssh/sshd_config),确认一下参数为

    PasswordAuthentication yes
    RSAAuthentication yes
    PubkeyAuthentication yes
    
    1. 查看 mysql 所有 user: SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;
  2. MHA check rel 报错:
    Q: error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln424] Error happened on checking configurations. Argument "1 # M-hM-/M-% MySQL M-fM-0M-8M-hM-?M-^\M-dM-8M-\rM-eM-^A..." isn't numeric in numeric ge (>=) at /usr/share/perl5/vendor_perl/MHA/ServerManager.pm line 1157.
    A: 很有可能是 mha 的配置文件中有中文,包括注释,去掉再试试

  3. 如何在 MySQL 间迁移数据
    迁移指定某个数据库
    数据源 MySQL 服务器:shell> mysqldump -uroot -p database_name > database_name.sql
    目标源 MySQL 服务器:

      mysql> create database_name;
      mysql> use database_name;
      mysql> source database_name.sql;
    

    官方资料

Links

Druid 極速體驗

該文基於 Druid 0.8.3.

該集羣的 relatime node 採用 indexing server 的方式,即 overload 和 middlerManger 的組合。Deep Storage 用 Hadoop(這裏假設已經有可用 hadoop 的集羣), 而數據灌入採用 traniquilityCore 模塊,並未用 kafaka 等消息隊列。
查詢用了 pydruid,非常簡單方便。

机器

結點都是單臺機器,沒有作 高可用性。

操作系統:CentOS release 6.7 (Final)

机器配置 数量 结点名
8核 8GB 100GB 1 Overload
16核 32GB 100GB 1 MiddlerManager
16核 64GB 200GB 1 Histrical
16核 32GB 100GB 1 Borker
8核 16GB 200GB 1 Coordinator & metadata store(mysql) & zookeeper

安裝

对所有结点机器 更新系统: yum -y upgrade

mysql 安裝和配置:

yun -y install mysql-server
mysql -u root
CREATE DATABASE druid DEFAULT CHARACTER SET utf8;
GRANT ALL ON druid.* TO 'druid'@'%' IDENTIFIED BY 'diurd'; 

zookeeper 安裝和配置:

curl http://www.gtlib.gatech.edu/pub/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz -o zookeeper-3.4.6.tar.gz
tar xzf zookeeper-3.4.6.tar.gz
cd zookeeper-3.4.6
cp conf/zoo_sample.cfg conf/zoo.cfg
./bin/zkServer.sh start
cd ..

下載 druid 安裝包,并解压缩:

wget http://static.druid.io/artifacts/releases/druid-0.8.3-bin.tar.gz
tar -zxvf druid-0.8.3-bin.tar.gz

進入根目錄:cd druid-0.8.3

更改 config 目錄下的各個配置文件,配置的詳細參數可以參看 官方文檔, 這裏是本集羣的一套配置文件

根據上一部配置文件中的信息,在響應節點機器上創建 druid 所需目錄(這一步很關鍵,若是遺漏,後續在啓動運行中會出現一些莫名的問題很折騰人)

  • MiddleManager Node: mkdir -p /druid/prod/discovery
  • Histrical Node: mkdir -p /tmp/druid/indexCache

編寫各個節點的啓動腳本,這裏有本集羣的所有結點啓動腳本

將包分發到各個節點,並啓動相應腳本: nohup sh ./start_node.sh &

數據灌入( Data Ingestion)

Data Ingestion 有很多方式,這裏直接通過官方提供的 tranquility 來實現。 Tranquility 提供了多個模塊,包括 core, server, Samza, Spark, Storm, Kafka, Flink。開發者可以根據自己的架構選擇合適的模塊,支持 Java 和 Scala。這也是官方非常推薦的方式。

這裏選用 Core 模塊,最新版本已經到了 0.7.4 。官方也給出了最新版本的 Java Demo,只是一個 Java 代碼和 配置文件,簡單構建了一個工程,沒跑通。

這裏用的 Tranquility Core 版本是 0.7.3。寫了一個簡單的 Java 版本的 Demo 作爲演示。工程用 Maven 構建,可以直接從 這裏 下載整個工程,在代碼裏修改好一些鏈接的基礎配置,直接可以運行代碼,或者生成 ingestion.jar 並運行 java -cp ./data-ingestion.jar com.ingestion.Ingestion

數據查詢

數據查詢直接用官方提供的 pydruid,不會有太多問題。
這裏直接上 Demo.

關鍵注意點

  1. 集羣時間同步,誤差儘量在 1s 內 (雖然官方文檔未指定,但最好能做到以避免不必要的麻煩)
  2. 整個集羣統一用 utc 時間
  3. 在相應機器上一定要記得 創建druid集羣 配置文件 中指定的響應目錄
  4. Data Ingestion 時常會遇到類似 「Message Drop」的問題,主要原因有兩個
    • Event 過了指定的有效時間,「Tranquility drops events outside the windowPeriod on the client side」。解決方案:丟棄這部分數據就 OK 了。
    • Historical 結點會把數據從 deep storage 拉到本地磁盤並且緩存到內存中,當緩存被耗盡會導致 index task 一直無法完成。那麼 MiddleManager 沒有多餘的進程去執行新的 task。解決方案:可以在 Coordinator(coordinator-node-host:port) 頁面配置中設定加載規則,例如只加載最近 30 天的數據規則可以是這樣#rule1: load 30PD #rule2: drop forever

最後

本文提到的 集羣配置、啓動腳本、Data Ingestion、查詢 等都已經放到了 github,直接 clone 到本地使用: git clone https://github.com/nepaul/DruidDemos.git

RESTful API 设计最佳实践

来自大厂的 RESTFul 规范

Resources

  1. how to design a good API and Wht it Matters.pdf
  2. RESTful API Designing guidelines — The best practices中文
  3. 10 Best Practices for Better RESTful API
  4. Best Practices for Designing a Pragmatic RESTful API
  5. stackoverflow: REST API Login Pattern
  6. 如何处理好前后端分离的 API 问题:
    i. API 设计应该由前端开发者来驱动的。后台只提供前端想要的数据,而不是反过来的。后台提供数据,前端从中选择需要的内容。
    ii. 使用文档规范 API
    iii. 契约测试:基于持续集成与自动化测试
  7. 👍👍A Massive Guide to Building a RESTful API for Your Mobile App

Tools

  1. Swagger:Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment

番外

  1. URLs are UI

ChatOps: Slack + Hubot

背景

在一些小项目或者说小公司中,开发人员往往要兼顾运维的工作。举个例子,当一个网站的新功能开发完毕后需要部署上线的时候,大致的步骤:通过 ssh 登录 CentOS,CD project-dir,update code,build,start server ...

重复,枯燥乏味!很多时候都希望有个人来帮忙做这些事情。那么,有可能嘛?

YES!ChatOps: Hubot + Slack

几个概念

  • Hubot: github 开源的提高生产效率工具(CoffeScript 编写, github 地址),可以自动化很多任务。
  • Slack: 湾区已经流行很久的集聊天群组、文件整合、 统一搜索、 大规模工具等于一体的团队协作工具。
  • ChatOps: Chat + Ops, 简单来说,通过聊天完成软件部署。关于 ChatOps,这篇文章阐述的不错,推荐!

简单的理解:Hubot 只是一个可定制并执行很多自动化任务的小程序(可以部署在本地或云端,当然必须联网),通过从 Slack 获取的 Token,两者很好的集成。从而让可以在 Slack 通过与 Hubot 聊天来完成一系列的自动化任务。算是一个 智能机器人 了。有趣新颖,再也不怕部署环境了。

下面开始介绍怎么创造一个“智能机器人”。

机器环境

可以将 Hubot 部署在本机或者云端,云端推荐用 Heroku(一般免费账户基本够用)。

暂时部署在本地:macOS Sierra(我的主力开发机) & Ubuntu Server 16.04(web 服务器)。

以下主要演示在 macOS 上的操作,Ubuntu 没有太多本质差异。

Hubot

安装和配置

  1. 安装 NodeJS(官网不同操作系统详细安装教程
  2. 通过 npm 安装 coffee-script hubot yo generator-hubot 以便生成和执行 hubot
  3. yeoman generator 生成 Hubot
  4. 配置 Hubot
# 1. 安装 NodeJS
brew update
brew install node 

# 2. 安装 coffee-script hubot yo generator-hubot
# 推荐墙内的小伙伴用 cnpm -> [npm install -g cnpm --registry=https://registry.npm.taobao.org]
npm install -g coffee-script hubot yo generator-hubot

# 3. 生成 hubot
mkdir my-hubot && cd my-hubot
yo hubot --adapter=slack
# 上面命令执行中,会有一系列的交互操作全部回车默认即可。成功后会在该目录下生成一系列的文件。

# 4. 配置 Hubot
# Hubot 默认集成了 hubot-redis-brain hubot-heroku-keepalive,这里暂时不需要
npm uninstall --save hubot-redis-brain hubot-heroku-keepalive
# 成功后从 external-scripts.json 文件中删除 hubot-redis-brain hubot-heroku-keepalive
# 删除 hubot-script.json
rm -rf hubot-scripts.json

# DONE!

调戏一下 Hubot

默认已经安装了一些插件,可以在 extrenal-scripts.json 文件中查看,对应插件的用法直接 Google 。

试一下 hubot-help,这个插件不用多说。

# 在 my-hubot 目录下,启动 Hubot
⇒  bin/hubot
my-hubot>
my-hubot> my-hubot help
my-hubot> Shell: my-hubot adapter - Reply with the adapter
my-hubot animate me <query> - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead.
my-hubot echo <text> - Reply back with <text>
my-hubot help - Displays all of the help commands that Hubot knows about.
my-hubot help <query> - Displays all help commands that match <query>.
my-hubot image me <query> - The Original. Queries Google Images for <query> and returns a random top result.
my-hubot map me <query> - Returns a map view of the area returned by `query`.
my-hubot mustache me <url|query> - Adds a mustache to the specified URL or query result.
my-hubot ping - Reply with pong
my-hubot pug bomb N - get N pugs
my-hubot pug me - Receive a pug
my-hubot the rules - Make sure hubot still knows the rules.
my-hubot time - Reply with current time
my-hubot translate me <phrase> - Searches for a translation for the <phrase> and then prints that bad boy out.
my-hubot translate me from <source> into <target> <phrase> - Translates <phrase> from <source> into <target>. Both <source> and <target> are optional
ship it - Display a motivation squirrel

Slack

  1. 注册登录
  2. 安装 Hubot 插件,成功后会自动生成一个 Token
  3. 记录 Token 以便后续与本地的 Hubot 集成

让 Slack 与 Hubot 一起工作

配置与启动

  1. 本地配置启动:非常简单,在 my-hubot 目录下执行一行命令即可,成功后会显示 "Slack client now connected":
HUBOT_SLACK_TOKEN=<your slack token> ./bin/hubot -a slack
  1. 切到 Slack,可以在 Slack 里与 Hubot 对话了!跟你在本地打命令行一样,只是不用打前面的 my-hubot 了。

  2. 在启动 hubot 的时候,不想每次都输入这么难记的命令。可以直接在 package.json 文件里加如下几行:

      "scripts": {
        "start": "./bin/hubot",
        "slack": "HUBOT_SLACK_TOKEN=xoxb-114806098885-9c9tZkxaRChQozjZLBhrVrgY ./bin/hubot --adapter slack"
      }
    • 本地启动:npm start
    • 集成到 Slack 启动:npm run slack

利用 hubot-script-shellcmd 来部署项目

hubot-script-shellcmd 顾名思义, 就是一个执行 shell 脚本的插件。

已经将之前那个 my-hubot 移植到了作为 Web 服务器的 Ubunter-Server-16 上(操作都是一样的)

  1. 安装 npm i --save hubot-script-shellcmd,在 external-scripts.json 中配置 hubot-script-shellcmd

  2. cp -R node_modules/hubot-script-shellcmd/bash .

  3. bash/handlers 目录下新增一个 shell 脚本,例如 deploy

    #!/bin/bash
    echo "Deploy ..."
    # 部署中想做的一些操作 ...
    echo "Successfully!"
    
    exit 0
  4. npm run slack

  5. 在 Slack 中执行 shellcmd deploy,效果图如下:

    slack-hubot-image

其他

Hubot 还能做更多事情。

可以用已有的很多插件完成丰富而有趣的事情。当然,也可以自己写 CoffeeScript 来完成更复杂的操作。

下一步打算用他将我 Hexo 博客文章的发布流程自动化一下。

另外,我是从 「湾区日报是如何运作的?」知道了 Slack + Hubot 这么个有趣的组合的。湾区日报每天推送五篇好文,推荐给大家。

第一个 VSCode 插件

VSCode,即 Visual Studio Code ,是 微软 的一个开源编辑器。快速、稳定,内置调试、git ,并且有类似 atom 和 sublime 的插件扩展机制。现在我基本以此来作为 Web 开发的编辑器,强烈推荐给大家。

背景

每次新建一个项目免不了配置 .editorconfig文件(可以从 官网 进一步了解 editorconfig ),里面的内容大同小异。
每次手工配置很麻烦,想通过一个命令智能生成常规的 .editorconfig文件,内容大致如下:

# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

搜索了 Extensions Marketplace,发现有一个 EditorConfig for VS Code插件功能类似,但是生成的文件内容还是不满足我的项目常用配置(内容如下)

root = true

[*]
indent_style = space
indent_size = 2

索性自己写一个!

前期准备

  1. 注册一个 Visual Studio Team Services 的帐号,以便后续编写以及发布插件到 Marketplace详细步骤 )。
  2. 步骤1 中的帐号主页中添加一个 Personal Access Token ( 详细步骤
  3. 安装 发布工具 vscenpm install -g vsce(当然这需要 NodeJS 环境)。
  4. 创建一个发布者:vsce create-publisher (your publisher name),交互过程中会需要输入 步骤2 中生成的 Token。vsce 会记录该 Token。
  5. 安装 yocodenpm install -g yo generator-code。可以通过 Yo Code 这个工具快速生成一个插件工程。

编码及发布

✌️插件的代码已经发布到 github ✌️

生成一个 插件工程:yo code,会有一些交互,基本默认就好。
主要关注 package.jsonextension.js这两个文件,前者主要是插件的基本配置,后者是插件代码的入口主文件。

package.json

{
    "name": "editorconfiggenerator",
    "activationEvents": [
        "onCommand:extension.generateEditorConfig"
    ],
    "main": "./src/extension",
    "contributes": {
        "commands": [
            {
                "command": "extension.generateEditorConfig",
                "title": "GenerateEditorConfig"
            }
        ]
    }
}

extension.generateEditorConfig:代码中注册的触发事件,command 相关的字段中必须统一
GenerateEditorConfig (commands -> title 字段值):shift + cmd + p 调出的命令行中输入的值。

发布

发布前建议好好书写 README.md 文件,以让用户知道这个插件的作用和使用方法。
发布的命令很简单:

cd your-extension-project-directory
vsce publish 语义化版本号

不了解语义化版本号的同学可以看 官网资料
vsce 提供了自动增加的版本号机制:major,minor,patch,例如: vsce publish major

另外,我的插件 EditorConfigGenerator 已经发布了,欢迎使用。

参考文档

  1. 基本介绍及教程
  2. API 文档
  3. 辅助工具

用 Collectd InfluxDB Grafana 来监控系统

企业级的运维监控方案有很多,Zabbix 享负盛名,小米的 Open-Falcon 做得也越来越好。

这次主要分享一套简易的基于几个开源项目的监控方案:Collectd + InfluxDB + Grafana。算不上企业级,但是监控几台服务器还是不在话下。

概念

  • InfluxDB:基于时间序列的数据库,非常适合作为系统 metric 的数据存储。目前版本已经迭代到 V1.1 了。背后的 influxdata 公司发展势头很好,也有很多其他产品。曾经也在 这边文章 里有所介绍。

  • Grafana: 一个已经非常有名的用来作为 metric 分析展现的 Dashboard。可以很方便地同其他开源工具继承,比如说同样有名的 Graphite 和 Elasticsearch 等。

  • Collectd: 用来收集系统和应用性能数据的工具,老牌并且应用广泛。通过各种配置可以收集非常丰富的数据。

简单来说,Collectd 定期收集机器性能数据并且发送到 InfluxDB 存储下来。Grafana 从 InfluxDB 中取出数据并分析展现。

机器环境

  • 服务端:负责存储数据并展现的服务器

    • 系统:Ubuntu-Server-16
    • 需要安装的应用:InfluxDB,Grafana,Collectd
  • 客户端:被监控的设备

    • 系统:CentOS-7

    • 需要安装的应用:Collectd

InfluxDB

只需安装在服务端,官方安装文档

安装

curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
source /etc/lsb-release
echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

sudo apt-get update && sudo apt-get install influxdb
sudo service influxdb start

配置

vim /etc/influxdb/influxdb.conf

取消以下内容的注释,修改 enable 参数为 true:

[[collectd]]
   enabled = true
   bind-address = ":25826"
   database = "collectd"
   retention-policy = ""
   typesdb = "/usr/share/collectd/types.db"

  # These next lines control how batching works. You should have this enabled
  # otherwise you could get dropped metrics or poor performance. Batching
  # will buffer points in memory if you have many coming in.

  # Flush if this many points get buffered
   batch-size = 5000

  # Number of batches that may be pending in memory
   batch-pending = 10

  # Flush at least this often even if we haven't hit buffer limit
   batch-timeout = "10s"

  # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max.
   read-buffer = 0

启动

sudo systemctl start influxdb

查看状态:sudo systemctl status influxdb

通过命令行工具连接:influx

Collectd

安装

安装在所有需要监控的客户端。

**服务端也必须安装!**否则 InfluxDB 配置 Collectd 后,会由于找不到 /usr/share/collectd/types.db 这个文件而无法启动!

sudo yum install epel-release
sudo yum install collectd

配置

取消以下参数的注释,并且修改 server 为你的 server IP

Hostname "本机的HostName"
<Plugin network>
       # client setup:
       Server "server-ip" "25826"
       <Server "server-ip" "25826">
       </Server>
</Plugin>
LoadPlugin network

查看配置是否有语法问题:collectd -t,配置正确的话没有任何输出信息。

启动

sudo systemctl start collectd

因为之前已经成功配置启动 InfluxDB,所以此时可以 collectd 可以定期收集客户端的性能数据了。默认配置下会收集 CPU,load,memory 等数据。可以在服务端用 influx 的 cli 工具登录查看以下:

$ influx
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 1.1.1
InfluxDB shell version: 1.1.1
> show databases
name: databases
name
----
_internal
collectd  # 这个就是我们数据存储的 DB

> use collectd
Using database collectd

> show measurements
name: measurements
name
----
cpu_value
interface_rx
interface_tx
load_longterm
load_midterm
load_shortterm
memory_value

Grafana

官方文档

只需要安装在 服务端。

安装

$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.2-1481203731_amd64.deb
$ sudo apt-get install -y adduser libfontconfig
$ sudo dpkg -i grafana_4.0.2-1481203731_amd64.deb

启动

sudo systemctl start grafana-server

浏览器打开:http://server-ip:3000

配置

直接在浏览器通过界面配置,登录的用户名和密码都是 admin

界面操作很简单,详见这里

一张最终的数据图

load

其他

Telegraf:Influxdata 出品的另一个开源的 时间序列数据收集工具。有很多的数据输入和输出插件,具体可以查看那官方文档。非常灵活,未来可以在自己的程序中应用会更有趣。

参考链接

云服务

  1. The million dollar engineering problem:Segment 团队被自己的 AWS 账单吓到了,他们就用了3个月时间集中火力削减 AWS 开支,最终结果:一年省下$100万。他们怎么办到的?详见本文。

WEB 身份认证之 JWT

JWT 简介

JWT 即 JSON Web Token, 是一种在 组件间(比如 web 开发中的 client 和 server 之间)安全传递信息的开放标准(RFC 7519)。JWT 可以通过数字签名加密,所以是相对安全可靠的。

使用场景

最常见的使用场景是用作 身份认证(Authentication, Web 和 Mobile 皆可),还可以用作 组件间传递安全信息的载体

组成

一个 JWT 由三个部分组成:Header, Playload, Signature:

// 1. Headers
// alg: 加密算法,比如 HMAC SHA256 或 RSA
// typ: toke 的类型
{
  "alg": "HS256",
  "typ": "JWT"
}

// 2. Payload
// 用户信息
// sub:常指用户 ID
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

// 3. Signature
// 服务端可以通过签名保证 JWT 并未被恶意修改,简单来说就是确认是否合法
// 如代码所示,利用 header 中声明的算法来生成,通常会在服务端指定一个 SECRET KEY,保证后期的安全校验
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  SECRET_KEY)

最后,服务端通过 点号(.) 拼接三个部分生成一个可以发往客户端的 JWT:

base64UrlEncode(header) + '.' + base64UrlEncode(payload) + signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

原理

官网的一张图很清晰地说明了整个交互的过程:

  1. 浏览器用用户名和密码发起登录请求
  2. 服务端验证后产生一个 JWT 返回
  3. 浏览器需要保存 token(HTML5 的 localStorage sessionStoreage 或者传统的 cookie),服务端不需要保存
  4. 浏览器在请求需要验证的资源时都需要带上 jwt,通常是在 HTTP header 中设置:Authorization: Bearer <token>

jwt-process

JWT 的优势

JWT 对比 基于 cookie 验证方式的优点(这篇文章写得很详细,以下简单罗列一下):

  1. Cross-domain / CORS: 可以对任何 server 发起 AJAX 请求 2. Stateless (a.k.a. Server side scalability): 服务端无需保存 token,扩展方便
  2. CDN: 可以把资源文件都放在 CDN 上,服务端其实只是提供 API
  3. Mobile ready: 移动端处理 jwt 比 cookie 容易多了
  4. CSRF: 没有 cookie
  5. Performance: 解密(HMACSHA256)比找session应该块多了
  6. Standard-based: RFC标准,语言库支持丰富,大厂(比如 Firebase, Google)使用
  7. Decoupling(架构去耦): 不需要绑定特定的身份验证方案

深入学习的一些资料

  1. 10 Things you should know about Tokens (亲切的中文翻译)
  2. Token based authentication in realtime frameworks like Socket.io
  3. 主要讲安全的 Cookies are bad for you: Improving web application security
  4. json-web-tokens-jwt-vs-sessions

Talk is cheap, show me the code

一个基于 jwt 的用户登录和注册小 demo

当然,也有很多易用靠谱的第三方库(前端都用了 angularjs):

  • angular-jwt, 有 JWT 的创造者 Auth0 出品
  • saterllizer:还支持第三方登录(google facebook twitter 等)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.