OPC

OPC是什么?
http://opcfoundation.cn/about/what-is-opc/index.aspx
http://blog.csdn.net/u013120247/article/details/50163147

HowToStartWithUtgard
https://openscada.atlassian.net/wiki/display/OP/HowToStartWithUtgard

控制系统经常用到的是DCS和PLC
目前常用的无线网络标准最流行的3个是ZigBee、Bluetooth和WiFi。

OPC client examples include utgard and jeasyopc
https://github.com/luoyan35714/OPC_Client

也可以不使用AccessBase方式,使用for循环轮询查看item的数值。
http://tonynju.iteye.com/blog/289929

模拟器
http://www.matrikonopc.cn/products/opc-drivers/opc-simulation-server.aspx
http://www.hifreud.com/2014/12/27/opc-1-install-MatrikonOPC-Server-for-Simulation-and-Test/
http://www.hifreud.com/2014/12/27/opc-2-what-is-opc/
http://www.hifreud.com/2014/12/27/opc-3-main-feature-in-opc/
http://www.hifreud.com/2014/12/27/opc-4-client-invoke-use-utgard/
http://www.hifreud.com/2014/12/27/opc-5-client-invode-use-JeasyOPC/

APP开发架构

NativeApp
跨平台解决方案:
WebApp
dist是指distribution,发布,
dest则是destination,目的。
facebook-reactnative

PhoneGap/Cordova

使用iOS、Android等原生的WebView控件,用浏览器,基本上不能混合开发
Phonegap在每个移动平台(iOS、android、blackberry等)中都实现了一套后台框架,分别与各平台系统API进行交互,从而调用其native API,对应用开发人员提供了统一的JS调用接口,即phonegap API,开发人员只需要采用html、js、css等web技术即可进行移动平台快速开发。
Phonegap的“一次编写,到处运行”是指应用程序开发只需编写前端代码,并且可完全复用到其他平台,复用到其他平台时需要另外搭建相应的开发环境才能运行。

android平台phonegap框架实现原理
http://blog.csdn.net/wuruixn/article/details/7405175

ionic

Ionic 底层打包使用 Cordova ( 和 Phonegap 一样 ) 底层打包用 Cordova 是不错的。 Ionic 是一个全堆栈的混合应用开发框架,可以理解成 Ionic = Cordova + AngularJS + Ionic UI

ionic app 优化三件套,让其更贴近原生app:
禁用ionic 自带的滚动效果
在低版本android中,Crosswalk WebView提供了比原生WebView更好的性能;但是相应的会使app体积大20m左右,这就是其唯一的缺点,但是为了性能,这点问题当然不是问题啦;
引入插件 ionic-native-transitions,这是我个人觉得对app体验最最重要的一步。这能使app的页面切换效果 “纵享丝滑”,告别ionic自带的页面切换卡顿效果!
需要调用支付,蓝牙什么的功能务必用 ionic,因为有 phonegap,后期可以给你省很多事
如果你只是做纯粹展示型的 app 那么 weex 和 rn 都可以,如果 react 熟就 rn,不熟怕麻烦还是 weex

ionic3 教程
http://www.jianshu.com/p/1baf40713c1c

weex / react native / ionic 技术选型
http://www.sunzhongwei.com/weex-react-native-ionic-technology-selection

什么是Bower?

Bower 是 twitter 推出的一款包管理工具,基于nodejs的模块化思想,通过 Bower 来管理模块间的联系。
“包”是指一系列有意义的资源的集合,在bower这里,更多体现在json文件,它是这些资源的配置文件,一个完整的包都应该有一个bower.json文件。
“管理”包含获取,下载,安装,更新,查找,注册等等一系列对资源的操作。

bower与npm
npm是专门管理node模块的管理工具,而bower是node的模块,因为bower是依赖node,npm和git。npm擅长的是管理node模块,而bower管理的范围更大,涉及html,css,js和图片等媒体资源。常在服务器端使用npm,而在客户端使用bower。

gulpjs
gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速度更快。

JSHint、JSCS、ESLint、JSLint
JSHint 可以帮助检测 JavaScript 代码中的错误和潜在的问题
JSCS 是一个 JavaScript 的代码风格检查工具,通过使用这两款 QA Tools 能在团队协作中大大提升代码的正确性、准确性、完整性、简洁性、统一性及易读性。

WebSocket

angular-websocket
https://www.npmjs.com/package/angular-websocket
在angular工程中使用angular-websocket:

#index.html中 
#app.js中 angular.module('appmodule1', ['angular-websocket'])
#controller中
app.controller('UnitsReportsCtrl', function($scope, $websocket) {
        if(!$scope.ws) {
            $scope.ws = $websocket("ws://localhost:8181");

            $scope.ws.onOpen(function (e) {
                console.log('Connection to server opened');
            });
            $scope.ws.onMessage(function (e) {
                console.log('received',e);
            });
        }
        $scope.ws.send('test11');
}

在nodejs中使用websocket
https://github.com/websockets/ws

蓝牙

每个service包含一个或多个characteristic(特征值)
每个特征值包含一个value 和多个 descriptor,在某个特征值的value中包含数据信息。

小米手环
http://www.cnblogs.com/wobeinianqing/p/5883135.html
http://www.jianshu.com/p/1dfba61e2a9d

其它
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html
https://developer.android.com/guide/topics/connectivity/bluetooth.html?hl=zh-cn#TheBasics
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html?hl=zh-cn
https://github.com/akexorcist/Android-BluetoothSPPLibrary
https://github.com/Jasonchenlijian/FastBle/issues
http://blog.csdn.net/dingjikerbo/article/details/49254573
https://github.com/dingjikerbo/BluetoothKit
http://blog.csdn.net/woshasanguo/article/details/41082395
https://my.oschina.net/tingzi/blog/215008
http://www.jianshu.com/p/2268cfedc051
http://www.cnblogs.com/cxk1995/p/5693979.html
http://blog.csdn.net/fangqiangqi/article/details/51510115

Framework7

Framework7 是一个开源免费的框架可以用来开发混合移动应用(原生和HTML混合)或者开发 iOS & Android 风格的WEB APP。也可以用来作为原型开发工具,可以迅速创建一个应用的原型。

MongoDB

mongodb命令行group分组和java代码中group分组
https://www.2cto.com/database/201607/528258.html
MongoDB Counting and Grouping
http://wiki.summercode.com/mongodb_aggregation_functions_and_ruby_counting_and_grouping
mongodb和spring集成中MongoTemplate的总结是使用方法
http://blog.csdn.net/ruishenh/article/details/12842331
MongoTemplate:增加数据。根据id查询,条件查询,聚合group 和 distinct
http://147175882.iteye.com/blog/1565378
Spring Data JPA – Reference Documentation
https://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/#repositories.query-methods.query-creation
Spring Data for Mongo 介绍
http://colobu.com/2014/12/03/Spring-Data-for-Mongo-Introduction/

MongoDB文档

https://docs.mongodb.com/
https://docs.mongodb.com/manual/
https://docs.mongodb.com/manual/crud/
MongoDB教程
http://www.yiibai.com/mongodb/mongodb_indexing.html
MongoDB 基础知识
https://segmentfault.com/a/1190000002694268?_ea=184402
Mongoose学习参考文档——基础篇
http://ourjs.com/detail/53ad24edb984bb4659000013
Spring Boot中使用MongoDB数据库
http://www.tuicool.com/articles/QjmIFnf
MongoDB学习笔记—Linux下搭建MongoDB环境
http://www.cnblogs.com/hanyinglong/archive/2016/07/21/5690611.html
Install MongoDB Community Edition on OS X
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/
MongoDB Tutorial
https://www.tutorialspoint.com/mongodb/index.htm

MongoDB将信息存储在BSON(Binary JSON)中,对海量数据存储有着很明显的优势。并且当需要一个无模式或模式灵活的数据结构时,MongoDB是一个不错的选择。MongoDB对数据结构的更改相对轻松和宽容,这是NoSQL解决方案的卖点。在MySQL世界中有许多改进使在线模式更改成为可能,只创建记录而不定义结构增加了MongoDB的灵活性。
选择MongoDB的另一个原因是它具有设置复制环境,内置分片和自动选择方面的功能。在MongoDB中设置复制环境很容易,自动选择过程允许从数据库在主数据库故障的情况下接管。内置分片允许简单的横向扩展。在MySQL环境中管理,设置和配置会很复杂。
MongoDB缺点:主要是无事物机制!

MySQL与MongoDB的操作对比
http://blog.csdn.net/suxinpingtao51/article/details/40981621
对比MySQL,你究竟在什么时候更需要MongoDB
http://www.csdn.net/article/2014-03-06/2818652-when-use-mongodb-rather-mysql

安装mongodb

https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
https://docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-ubuntu/

MongoDB是免费的,有Enterprise和Community两个版本,在文档中可以看到差异主要体现在安全认证、系统认证等方面。

## Enterprise-Only Options:
#auditLog:
#snmp:

MongoDB安装部署手稿

修改端口等配置

vi /etc/mongod.conf
#修改端口和监听IP
# network interfaces
net:
  port: 27017
  #bindIp: 127.0.0.1
  #允许本机所有ip
  bindIp: 0.0.0.0

spring-data-mongodb

http://docs.spring.io/spring-data/data-document/docs/current/reference/html/
Java操作MongoDB采用MongoRepository仓库进行条件查询
http://blog.csdn.net/qinsihang/article/details/19921981

常用查询

./mongod -version
mongo #默认参数为 localhost:27017
mongo localhost:14000
help
show dbs
use dbname1
db.auth('username','password');
show collections
db.collectionName1.find()
#查看索引
db.collectionName1.getIndexes()
#查看版本
db.version()
#创建索引
db.collectionName1.ensureIndex({"_id":1})

常用修改

db.collectionName1.update({"_id" : ObjectId("58d0f91a7e113c661b0fc997")},{$set:{"code":"11112222"}})
db.collectionName1.insert({"name" : "abc","alias" : "123"})
#修改字段名
db.collectionName1.update({}, {$rename : {"oldColumnName" : "newColumnName"}}, false, true)

mongo3.0备份还原数据

#备份
~/mongodb/bin/mongodump -h localhost:27017 -d my_db -o ./
#还原
~/mongodb/bin/mongorestore -h localhost:27017 -d my_db ~/mongo-db/20170705/my_db --drop

mongoDB 2.0 文件目录

配置文件   /etc/mongod.conf 
数据库日志 /var/log/mongodb
数据库文件 /var/lib/mongodb
#关闭和启动数据库服务
sudo service mongod stop
sudo service mongod start

日志中:”nscanned” 表示查询了多少个文档。

MongoDB学习笔记(索引)
http://www.cnblogs.com/stephen-liu74/archive/2012/08/01/2561557.html

手动启动Mongo

cd  ~/mongodb/bin/
./mongod -dbpath=../data -logpath=../log/mongodb.log --logappend&
~/mongodb/bin/mongod -config  ~/mongodb/etc/mongodb.conf
./mongod -config ../etc/mongodb.conf --fork
#mongodb config file
dbpath=../data/db
logpath=../mongodb.log
logappend = true
port = 14000
fork = false
httpinterface=true

关闭数据库

# mongo localhost:27017
> use admin
> db.shutdownServer()

查询示例:

操作语句
修改多行
db.getCollection('operateRecord').update({"operateType":"门禁控制"},{"$set":{"operateType":"door"}},{multi: true})
删除列
db.User.update({},{$unset:{'operateTypel':''}},false, true)

常用查询 
db.getCollection('devices').find({name:/^mic/}).sort({display_name:1})
db.getCollection('devices').find({name:/^mic/,display_name:/^圆桌/},{_id:1}).sort({mic_router_id:1,name:1})
db.getCollection('devices').find({name:/^mic/,display_name:/^二层/},{_id:1}).sort({mic_router_id:1,name:1})
db.getCollection('alarmRecord').find({stateTime:{'$lt':new Date('2017/03/15')}}).count()
db.getCollection('alarmRecord').remove({stateTime:{'$lt':new Date('2017/03/16')}})
db.getCollection('devicegroups').find({tags:[‘aaaa’]})  数组中查找
db.getCollection('devices').find({name:/^decoder/}) 所有网络音频编解码器
db.getCollection('devices').find({device_type:ObjectId("585601376868180438aea058")})   所有门禁
db.getCollection('devices').find({device_type:ObjectId("59015c66dece7169709a02f4"))}) 所有安防摄像头
db.getCollection('devices').find({name:{$in:["door_2_40","door_2_41"]}})
db.Alert.find({collectorId:{$exists:true}})

添加
db.UnitType.insert({"name" : "CarelPJ0003","alias" : "qhtf-PJ0003"})

修改
db.UnitType.update({"_id" : ObjectId("583cca533b5e105d024c79f7")},{$set:{"name":"YIDE-HP 020"}})
db.UnitType.update({"_id" : ObjectId("599a3e7e80577cc54e0f4eb4")},{$unset:{"template":"lsqk-1"}})
db.Alert.update({collectorId:{$exists:true}},{$set:{"unitId":ObjectId("000000000000000000000000")}},false,true)

统计分路器个数
db.getCollection('devices').group({
    key: {mic_router_id: 1},
    cond: {name:/^mic/},
    reduce: function (curr, result) {
        result.count++;
    },
    initial: {
        count: 0
    }
});

按类型列出设备 //http://www.xker.com/page/e2015/07/205772.html
db.getCollection('devices').group({
    key: {device_type: 1},
    reduce: function (curr, result) {
        result.count++;
        result.ids.push(curr._id);
    },
    initial: {
        count: 0,
        ids:[]
    }
});

Lookup多表关联处理
db.getCollection('devicetypes').aggregate([{$lookup:{from: "devices", localField:"_id", foreignField: "device_type", as: "devices"}}
,{$project:{_id:1,name:1,devices:1}}
,{$group: {_id: "$_id", deviceTypeName: {$first:"$name"}, deviceIds:{$push:"$devices._id"}, count:{$sum: 1} }}
])
或者
db.getCollection('devices').aggregate([{$lookup:{from: "devicetypes", localField:"device_type", foreignField: "_id", as: "deviceType"}}
,{$group: {_id:{_id:"$deviceType._id", display_name:"$deviceType.display_name", name:"$deviceType.name"}, deviceIds:{$push:"$_id"}, count:{$sum: 1} }}
])
或者
db.getCollection('devices').aggregate([{$lookup:{from: "devicetypes", localField:"device_type", foreignField: "_id", as: "deviceType"}}
,{$group: {_id:"$deviceType._id", display_name:{$first:"$deviceType.display_name"}, name:{$first:"$deviceType.name"}, deviceIds:{$push:"$_id"}, count:{$sum: 1} }}
])

各个机组的最新的监测记录 https://docs.mongodb.com/manual/reference/operator/aggregation/max/
db.getCollection('RealtimeLog').aggregate(
   [
        {$match: {"unitId": {"$in":[ObjectId("596dac89c13a10339936610b")]}}},
     {
       $group:
         {
           _id: "$unitId",
          maxId: { $max: "$_id" }
         }
     }
   ]
)

统计各个unitId的条数
db.getCollection('Alert').aggregate([{$group : {_id : "$unitId", num_tutorial : {$sum : 1}}}])

数据库加密码

use admin
db.auth("userForAdmin","passForAdmin");
#use 即可新建数据库
use newdb1
db.createUser({user: "userForNewDB1", pwd: "123456", roles: [{ role: "dbOwner", db: "newdb1" }]})

supervisor

Linux的后台进程运行有好几种方法,例如nohup,screen等,但是一个服务程序要可靠地在后台运行,就需要把它做成daemon,最好还能监控进程状态,在意外结束时能自动重启。
Supervisor就是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,能做开机启动,并监控进程状态,异常退出时能自动重启,它还提供了web管理界面。

安装supervisor
$ sudo apt-get install supervisor
卸载supervisor
$ sudo apt-get remove supervisor
安装完成后,查看其配置文件
$ vi /etc/supervisor/supervisord.conf
查看到自定义配置存放目录为 files=/etc/supervisor/conf.d/*.conf
$ cd /etc/supervisor/conf.d
创建要自启动的服务配置
$ sudo vi service1.conf

配置解释:

[program:service1] #服务名称,在supervisor中可以用这个名字来管理该程序。
command=  #启动程序的命令
directory=/home/user1 #相当于在该目录下执行程序
autostart=true #设置随supervisor的启动而启动
autorestart=true #程序停止之后是否需要重新将其启动
startsecs=10 #重新启动时,等待的时间
startretries=36 #重启程序的次数
redirect_stderr=true #是否将程序错误信息重定向的到文件
stdout_logfile=/home/user1/%(program_name)s_log.txt #将程序输出重定向到该文件
stderr_logfile=/home/user1/%(program_name)s_err.txt #将程序错误信息重定向到该文件
numprocs = 2
numprocs_start = 8850
user = #系统用户名
process_name = 163gs-%(process_num)s

配置好后重启supervisor服务

sudo service supervisor restart

supervisorctl 是命令行管理工具,它的查数查看

supervisorctl help
supervisorctl version
default commands (type help ):
=====================================
add    clear  fg        open  quit    remove  restart   start   stop  update 
avail  exit   maintail  pid   reload  reread  shutdown  status  tail  version

Supervisor2.x版本有一些不同:

配置文件位置 /etc/supervisord.conf
需要在supervisord.conf尾部按示例添加服务配置
服务名称是 supervisord
sudo service supervisord restart

更多配置参考
http://supervisord.org/configuration.html
http://www.jianshu.com/p/65f31f5a4e84
http://www.jianshu.com/p/805977544d7f
http://www.linuxidc.com/Linux/2015-04/116701.htm
http://www.cnblogs.com/haoliansheng/p/6611714.html
http://www.cnblogs.com/zhangym/p/5833353.html

错误处理

报错 unix:///tmp/supervisor.sock no such file
出现上述错误的原因是supervisord并未正常启动,重新启动supervisord即可。
supervisord -c /etc/supervisor/supervisord.conf

SSH代理

通过ssh代理功能连接到内网linux服务器

需要通过一台公网主机代理

  1. 建立内服到云的反向代理
  2. 建立云服上的正向代理
  3. 在个人机器上通过云服ssh到内服

下面三行命令分别在内网服务器、云服务器、和个人电脑上执行。

ssh -fCNR 8081:localhost:22 云用户@云IP
ssh -fCNL "*:8082:localhost:8081" localhost
ssh -p 8082 内服用户@云IP

8081是云服上端口,用来与内服上的22端口绑定。
8082为云服上转发端口,将数据转发到8081端口。
*表示接受来自任意机器的访问。
https://segmentfault.com/a/1190000002718360

SSH 参数解释

  • -f 后台运行
  • -C 允许压缩数据
  • -N 不执行任何命令
  • -R 将端口绑定到远程服务器,反向代理
  • -L 将端口绑定到本地客户端,正向代理

sshkey免密码

ssh即secure shell,即安全shell。sshkey用来加密传输。
加密传输的算法有多种,git可使用rsa,rsa使用一对特定的数字,这两个数字就是在使用git和github的时候所遇到的public key(公钥)以及private key(私钥)。公钥就是那个用来加密的数字,在本机生成了公钥之后,要上传到github。从github发回来的,是用公钥加密过的数据,可以用本地的私钥来还原。不管是公钥还是私钥,丢失一个都不能用了,解决方法也很简单,重新再生成一次,然后在github.com里再设置一次。
方法一,密钥验证。安全、配置简单、同时ssh、scp、sftp等登录都免去了输入密码的麻烦。

查看~/.ssh下是否已经生成id_rsa.pub,如果已存在可以直接使用它,覆盖它可能会影响现有服务正常使用。
如果没有则客户端生成密匙对,最后在~/.ssh下生成id_rsa.pub公钥。
#ssh-keygen -t rsa
然后将公钥通过scp命令上传到服务器上,将本地生成的公钥拷贝到远程服务器的下并改名为authorized_keys。
#scp ~/.ssh/id_rsa.pub 用户名@服务器的ip:~/.ssh/authorized_keys

方法二,通过sshpass明文传送密码匙,安全性不高。

安装sshpass允许你用 -p 参数指定明文密码,然后直接登录远程服务器。例如:
# sudo apt-get install sshpass
sshpass允许用 -p 参数指定明文密码,然后直接登录远程服务器
# sshpass -p '密码' ssh 用户名@服务器ip

http://www.linuxidc.com/Linux/2011-02/31921.htm
http://www.cnblogs.com/ggjucheng/archive/2012/08/19/2646346.html

开机自动运行ssh命令建立反向代理

通过supervisor配置自启动,ssh服务配置示例:

[program:service2]
command=ssh -fCNR 8081:localhost:22 云用户@云IP
autorstart=true #设置随supervisor的启动而启动
directory=~ #相当于在该目录下执行程序
autorestart=true #程序停止之后是否需要重新将其启动
startsecs=10 #重新启动时,等待的时间
startretries=36 #重启程序的次数
redirect_stderr=true #是否将程序错误信息重定向的到文件
stdout_logfile=~/%(program_name)s_log.txt #将程序输出重定向到该文件
stderr_logfile=~/%(program_name)s_err.txt #将程序错误信息重定向到该文件
numprocs = 2
numprocs_start = 8850
user = #系统用户名
process_name = 163gs-%(process_num)s

如果日志中报ssh “permissions are too open” error
.ssh/id_rsa 不要设置为777权限,Chmod 400 即可。

自动ssh登录脚本

#!/usr/bin/expect
set timeout 10
spawn ssh root@ip
expect {
    "*yes/no*" {
        send "yes\n";
        exp_continue;
    }
    "*password:*" {
        send "密码\r";
        exp_continue;
    }
}
interact

Ubuntu

http://cn.ubuntu.com/

切换桌面
启动到登录界面时,可以ctrl+alt+F1…7,切换桌面

解压tgz
tar -zxvf xxxx.tgz

terminal中出现菱形乱码修改方法

vim /var/lib/locales/supported.d/local
里面有这行内容
en_US.UTF-8 UTF-8

sudo vim /etc/default/locale 修改为
LANG=”en_US.UTF-8″
LANGUAGE=”en_US:en”

重启动

安装boost

# apt-cache search boost
# apt-get install libboost-dev

安装最新的版本
到https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2/download下载
https://jaist.dl.sourceforge.net/project/boost/boost/1.63.0/boost_1_63_0.tar.bz2

# tar --bzip2 -xvf boost_1_63_0.tar.bz2
# cd boost_1_63_0
# ./bootstrap.sh  可以看到在当前目录下生成了安装工具bjam和b2
# ./bjam  编译时间比较长
# ./bjam install 安装完毕后的头文件默认是在/usr/local/include目录下,.a和.so在/usr/local/lib目录下。

http://blog.csdn.net/chinawangfei/article/details/50351371
http://blog.csdn.net/sinat_23857245/article/details/45225147
http://blog.csdn.net/yhrun/article/details/8099630

nginx的安装目录

sudo apt-get install nginx
完成后的安装目录在 /etc/nginx, nginx命令文件位置在 /etc/init.d/中
nginx -v #nginx version: nginx/1.4.6 (Ubuntu)
可能新的安装版本位置在/usr/local/nginx,mac上版本是 nginx version: nginx/1.10.2

查看版本
cat /etc/issue

nodejs

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。V8引擎速度非常快,不用担心多线程,锁,并行计算产生的问题。
如果你编码不认真,java会给你丘,而nodejs会给你很多坑,使用WebStorm开发有的错误会报错,有的错误则会运行通过,产生意料之外的行为。

node擅长处理io密集型业务,在处理CPU密集计算的时候可选择以下方案:
1.node业务逻辑都以单线程进行处理,那如果其中包括耗时的复杂计算,可以以rpc 的方式让其他编译型语言处理,node 只负责搬运。 也就是说node负责接受请求、执行io、发送回复,其他逻辑由擅长计算的语言处理。
2.业务逻辑交给node,便于快速开发。其他内容交给其他语言,或者直接交给c++,用node-gyp编译一下。

Node.js Manual & Documentation
http://nodejs.cn/api/
http://shouce.qdfuns.com/nodejs/index.html

socket.connect参数顺序

创建TCP客户端的坑之connect的参数顺序是先port再host:

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 8888;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    // 建立连接后立即向服务器发送数据,服务器将收到这些数据 
    client.write('message');
});

pm2

pm2 = P (rocess) M (anager)2,是可以用于生产环境的Nodejs的进程管理工具,它内置一个负载均衡,可以保证服务不会中断一直在线,并且提供0秒reload功能,还有其他一系列进程管理、监控功能。

pm2的安装和使用

pm2 start app.js
pm2 save
pm2 startup
pm2 reload all
pm2 list
pm2 restart [id]

~# ls -a显示所有包括隐藏的文件,可以看到.pm2文件夹

更多pm2常用的命令用法介绍
http://i5ting.github.io/node-deploy-practice/
http://www.111cn.net/sys/linux/120062.htm
http://www.pangjian.info/2016/12/02/deploy-nodejs-pm2-1/?utm_medium=referral

缓存

nodejs通过文件名缓存加载过的模块,这里是全局缓存,不是页面内缓存。

grpc

安装grpc-tools
$ sudo npm install grpc-tools -g
把proto文件生成js文件
$ /usr/local/lib/node_modules/grpc-tools/bin/protoc --js_out=import_style=commonjs,binary:. --grpc_out=. --plugin=protoc-gen-grpc=/usr/local/lib/node_modules/grpc-tools/bin/grpc_node_plugin *.proto

http参数

参数名是区分大小写的,不存在的参数值是undefined
取get地址?后面的传参
var id=req.query.id;
取rest路径中的参数
var id = req.params.id;
取post时json对象中的参数
id=req.body.id;

express超时重复请求

3种解决办法
1.httpserver设置超时函数
var app = express();
var http = require(‘http’);
var server = http.createServer(app);
server.on(‘timeout’, onTimeout);
function onTimeout(err) {
}
2.加大超时时间
server.timeout=10*60*1000;
3.request或response设置超时处理方法
router.post(‘/xxx’,function(req,res,next){
req.setTimeout(240000,function () {
});
}
http://blog.csdn.net/puncha/article/details/9378197

async

npm install async –save,其中–save参数会在工程package.json中dependencies中增加一条依赖;
async主要实现了三个部分的流程控制功能:
集合: Collections
流程控制: Control Flow
工具类: Utils

Nodejs异步流程控制Async


Async提供了很多针对集合的函数,简化对集合的异步操作步骤
https://my.oschina.net/chinacaptain/blog/469810

常用的流程控制:
series 串行,保证顺序不依赖
parallel 并行
waterfall 依赖串行、瀑布流,之间需要传递结果时使用
auto 并行加依赖串行
apply 给函数预置第一个参数,然后返回一个新的函数。

async.series({
	one: function(callback){
		callback(null, 1);
	},
	two: function(callback){
		callback(null, 2);
	}
},function(err, results) {
	console.log(results);
});
或者
async.series([
            function(callback){
                callback(null, 1);
            },
            function(callback){
                callback(null, 2);
            }
        ],function(err, results) {
            console.log(results);
        });

socket超时

var socket = new net.Socket(); 创建后
socket.setTimeout(10 * 1000, function () {
if(!idle) {
console.log(‘timeout not idle’);
if (callback) {
callback(false, {message: ‘请求超时’});
callback = null;
}
}else{
console.log(‘timeout idle’);
}
});
不执行connect或write,10秒后会打印timeout idle。
等待9秒后再执行connect,如果connect很久,会在connect开始10秒后打印timeout not idle。
即创建socket和connect或write会开始新一轮超时计时。但不能多次设置settimeout,会引发emit数量警告。
idle为自定义的状态,在connect或wirte时设置idle=false。

安装最新稳定版本
https://segmentfault.com/a/1190000007542620

淘宝NPM镜像CNPM
http://npm.taobao.org/
npm install -g cnpm –registry=https://registry.npm.taobao.org

Promise

Promise.reduce 方法才是一个顺序执行 Promise 的方法,一些顺序执行的方法,比如 Promise.mapSeries 和 Promise.each ,都是基于 Promise.reduce 来实现的,这里的 reduce 和 Array.reduce 一样。

环境变量 get-env

#app.js中代码:
app.env = require('get-env')({
  init_env1:'init_env1',
  init_env2:'init_env2',
});

#根据以上代码,在命令行中调用时有效的NODE_ENV值有:dev,prod,init_env1,init_env2
export NODE_ENV=init_env1
node app.js 

传递参数

例如:node const-generate.js cx-kqy.txt
process.argv的值相当于是把整个命令按空格分割成字符串数组。

var arguments = process.argv.splice(2);
console.log('所传递的参数是:', arguments);
process.argv.forEach(function (val, index, array) {
    console.log(index + ': ' + val);
});

网络基础

子网掩码

255.255.0.0 表示192.168.(0 – 255).(0 – 255)的IP地址都在同一网段内。
255.255.255.0 表示192.168.0.(0 – 255)的IP地址都在同一网段内。

A、B、C类IP地址

IP地址是互联网上进行寻址的地址编码,IP地址有4个字节,32位组成。为了区分IP地址,将IP地址划分为A类,B类,C类。
C类地址第1字节、第2字节和第3个字节为网络地址,第4个字节为主机地址。第1个字节的前三位固定为110。地址范围 192.0.0.0到223.255.255.255,私有地址 192.168.0.0到192.168.255.255,默认子网掩码 255.255.255.0,第1个字节的二进制值前三位位必须是“110”,即11000000开始到11011111结束,所以第一段的范围为192~223。
一个C类地址是由3个字节的网络地址和1个字节的主机地址组成。每个C类地址可连接254台主机(0是网络号不可用, 255是广播地址,除去这2个,可用的就是254个地址),Internet有2097152个C类地址段(32*256*256),有532676608个地址(32*256*256*254)。

如果电脑超过了254台,如果子网掩码设为255.255.255.0,需要有2个网段,不同网段下的电脑需要路由器或者三层交换机才能互相访问。

双网卡设置内外网

为默认网关(default gateway)只能是一个!删掉局域网的网关配置。
http://blog.csdn.net/chenlycly/article/details/52136960

笔记本同时连接宽带和WIFI,设置上网优先顺序:打开网络偏好设置/设定服务顺序

Linux命令

wget是一种下载软件类似与迅雷 如果要下载一个软件 我们可以直接: wget 下载地址
apt-get是ubuntu下的一个软件安装方式,它是基于debain。
yum是redhat、centos下的一个软件安装方式,它是基于Linux的。
aptitude与 apt-get 一样,是 Debian 及其衍生系统中功能极其强大的包管理工具。与 apt-get 不同的是,aptitude在处理依赖问题上更佳一些。举例来说,aptitude在删除一个包时,会同时删除本身所依赖的包。这样,系统中不会残留无用的包,整个系统更为干净。

安装命令

一般来说著名的linux系统基本上分两大类:

1.社区组织维护的发行版本 Debian系列:Debian、Ubuntu等
apt-get:Advanced Packaging Tool,apt是Debian Linux发行版中的APT软件包管理工具。所有基于Debian的发行都使用这个包管理系统。deb包可以把一个应用的文件包在一起,类似Windows上的安装文件。

一般可以通过使用ppa/源方式或下载两种方式安装软件。
Ubuntu 安装 JDK 7 / JDK8 的两种方式
http://www.cnblogs.com/a2211009/p/4265225.html
如果在ubuntu上报 add-apt-repository: command not found,先安装python。
sudo apt-get install python-software-properties
sudo apt-get install software-properties-common
//移除
sudo apt-get remove xxx

2.商业公司维护的发行版本 RedHat系列:Redhat、Centos、Fedora等
Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器。基於RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。
简单点说, rpm 只能安装已经下载到本地机器上的rpm 包. yum能在线下载并安装rpm包,能更新系统,且还能自动处理包与包之间的依赖问题。

查看资源信息
yum info supervisor

修改网络

服务器地址设置为static,不使用dhcp
ifconfig
sudo vim /etc/network/interfaces
sudo vim /etc/resolv.conf
sudo /etc/init.d/networking restart 可能不起作用
sudo reboot

另外长按重置路由器要在带电时操作。

搜索

grep全称是Global Regular Expression Print,表示全局正则表达式版本,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
grep默认对字母大小写敏感,选项-i可以指定为不敏感

grep 'abc' *.java
#递归查找所有js文件中的setting
grep -r 'setting' ./ --include='*.js'
$ ps -ef | grep java

常用命令

netstat -anptl 查看服务监听端口
tar -zxvf xxxx.tgz 解压压缩包
#移动当前目录下的全部内容到另一个目录中
mv ./* ../dir2/
合并目录
cp -frap source_dir/* dest_dir/
查看目录下各目录文件大小:
cd到上级目录,然后输入一条命令即可查询每个子目录所占用的空间大小,可以更改–max-depth参数的值,该参数表示查询子目录的层级,当前为1层。
du -h –max-depth=1

查看当前系统的发行版信息

lsb_release命令用来 prints certain LSB (Linux Standard Base) and Distribution information。
系统上如果没有安装了这个命令,还可以通过cat /etc/issue 查看。

lsb_release -a
lsb_release -d -s 
cat /etc/issue
head -1 /etc/issue

查看Centos系统信息

cat /etc/redhat-release #查看os版本
free -h #查看内存使用
uname -a #查看内核/操作系统/CPU信息
uname -r #查看内核版本,4.2.0-27-generic

http://www.centoscn.com/CentOS/help/2013/0728/738.html

tcpdump抓包工具

tcpdump是linux命令行下常用的的一个抓包工具
http://www.45it.com/linux/201409/37882.htm

vi命令

:$ 跳到文件最后一行,:0或:1 跳到文件第一行
s
hift + g 跳到文件最后一行,gg 跳到文件第一行。

性能查看

Linux服务器I/O过高原因及解决方法
http://www.linuxidc.com/Linux/2016-09/134813.htm

统计代码行数

find . -name "*.java"|xargs wc -l|grep "total"|awk '{print $1}'  
find . -name "*.java"|xargs cat|wc -l

查看端口及服务

lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。

#查看端口是否在使用中
lsof -i :14000

linux sed

sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作

写内容到文件
echo ‘内容’ > 文件

查看进程
ps 或 top

JVM

JVM

JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

Java语言的一个非常重要的特点就是与平台的无关性,使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码,Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

http://www.mamicode.com/info-detail-1028149.html

HotSpot VM

HotSpot VM是绝对的主流的JVM。大家用它的时候很可能就没想过还有别的选择,或者是为了迁就依赖了Oracle/Sun JDK某些具体实现的烂代码而选择用HotSpot VM省点心。Oracle / Sun JDK、OpenJDK的各种变种(例如IcedTea、Zulu),用的都是相同核心的HotSpot VM。从Java SE 7开始,HotSpot VM就是Java规范的“参考实现”(RI,Reference Implementation)。把它叫做“标准JVM”完全不为过。当大家说起“Java性能如何如何”、“Java有多少种GC”、“JVM如何调优”云云,经常默认说的就是特指HotSpot VM。可见其“主流性”。JDK8的HotSpot VM已经是以前的HotSpot VM与JRockit VM的合并版,也就是传说中的“HotRockit”,只是产品里名字还是叫HotSpot VM。不过要留意的是,这里我说的HotSpot VM特指“正常配置”版,而不包括“Zero / Shark”版。Wikipedia那个页面上把后者称为“Zero Port”。用这个版本的人应该相当少,很多时候它的release版都build不成功…

JVM调优-分代垃圾回收

分代垃圾回收采用分而治之的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

虚拟机中的共划分为三个代:年轻代(Young Generation)、年老代(Old Generation)和持久代
(Permanent Generation)。

年轻代
所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

老年代
在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

持久代
持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。

什么情况下触发垃圾回收?

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。

Scavenge GC(搜寻)
一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Full GC
对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比ScavengeGC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:
· 年老代(Tenured)被写满
· 持久代(Perm)被写满
· System.gc()被显示调用

从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

特别注意,在程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。

https://my.oschina.net/ydsakyclguozi/blog/404389