2017年12月6日 星期三

Node.js

開發botframework可以選擇c#或nodejs.
選nodejs的好處就是用javascript開發,
如果對javascript有一定熟悉度的話,
可以省去學習成本。
但Node.js
今年真的蠻困擾的,
例如 分支事件 (https://technews.tw/2017/09/07/node-js-leaders-fight-for-its-survival/)
node.js之父 公開說golang比nodejs好(https://www.mappingthejourney.com/single-post/2017/08/31/episode-8-interview-with-ryan-dahl-creator-of-nodejs/)
主要原因是 大家發現 Node.js 當網站訪問量大時,效能難以調挍等問題。
不過其實還是可以再雲上針對這些問題做一些優化,
例如: AWS 可以用cloudfront針對網頁做cache等設計,或是動態增生instance等.
But,我就是不想管更後端的事情,才會從nodejs開始啊!!!!!!
算了,不管,總之,
nodejs的生態系統完善,
幾乎要什麼有什麼!
而golang應該還有很長一段路要走。
所以,
還是先用nodejs吧!
而且在botframwork
https://github.com/Microsoft/BotBuilder
已經有提供許多相關範例,
大家可以參考使用。

Type script

開發Botframework 可以選c# 或node.js
而node.js是用JavaScript語法。
故可以使用type script ,
但主要是講botframework,
故 Type script 的部份,
讓我一章帶過吧。
TypeScript具有类型系统,且是JavaScript的超集。 它可以编译成普通的JavaScript代码。 TypeScript支持任意浏览器,任意环境,任意系统并且是开源的。
閉人在從 andorid 轉到開發 node.js應用時,
最大的困擾就是,
js無法再開發階段就可以偵錯。
例如
let a = i=>i+1;
我想要的得到的是 數字 相加的結果。
可是當我誤輸入 a("a"),也是會回傳 "a1",也是不會報錯,
這可是天與地一般的差距啊。
用 typescript
let a =(i:int)=i+1
若我輸入 a("a") 就會先報紅,
而不用等到最後輸出結果時,
才會發現這不是我要的,
這是其中一個最基本的好處。
*註 botframework 本身就是使用 type script 做開發。

前言. 選擇 botframework 的優缺點

假設你是要開發FB的chatbot,
且不具有程式背景(或懶得code),
但邏況能力還行的話,
那建議你可以直接採用 chatfuel ,
chatfuel 聽說是台灣團隊所開發,
且直接被FB給投資。
重點是,
Chatfuel有UI介面,
你只要拉一拉 連一連,就可以完成大部分的需求了,幾乎用不到任何code,但如果你想寫,也是有部分的支援。
而且,
chatfuel權限是直接被FB開啟的,
你不需要去跟FB要權限就可以做很多事,
例如 取得user profile...(申請fb權限,要審核,真的很麻煩!)
而且!!! 台灣某大銀行的FB chatbot是用企畫人員 chatfuel 拉出來,
然後該銀行就發新聞稿,自已站在潮流之上了,而且運作的還ok!。(廢話,chatfuel這麼多人在maintain 怎麼可能會差)
但是,
相對的,當然也會受限於Chatfuel的UI介面,
而使你的Chat bot 無法靈活開發,
達到一些,你所希望的功能,
另外,因為A.I.是採取chatfuel所訓練好的,
所以每個Bot 可能會交談起來都是固定的模式。
假設你有跨平臺的需求slack telegram Skype...
也是不能直接套用的。
如果你會 c# 或 node js,
那你就可以試一試 botframework,
botframework其實就是一套腳本+狀態的機制。
採用的好處就是你直接可以依照這個框架,來撰寫你的整個chatbot流程,
而不用從 message api 開始作一系列的發展。
但目前為止,最大的壞處,就是m$因為該公司有Cloud的產品,
為了帶動該Cloud的發展,
硬是綁在一起,
導致這麼好的一個框架,
得先連到美國作轉發,
所以整個就會慢。
*註:因為 Line不被 dev.botframework.com 所支持,
所以我自幹line builder 時,
就順便把轉發這個問題給幹掉了。
不過我FB messenger 的部分還是先採用 dev.botframework.com ,因為 npm 上的 FB builder都沒在做更新。
而FB又很愛改,所以先採用好了,以後再看看要不要幫忙 maintain FB builder.

2017年10月17日 星期二

connect pppoe by applescript

tell application "System Events"
tell network preferences
connect service "PPPoE"
end tell

end tell

tell application "System Events"
tell network preferences
disconnect service "PPPoE"
end tell
end tell

2017年9月11日 星期一

爬蟲 chromeless

https://github.com/graphcool/chromeless
可以無套串 AWS lambda
用serverless這套

2017年9月2日 星期六

aws cloudfront s3 image 設定header expires 之路

s3 加 lamda function
直接加上metadata
加content type
加expires

cloudfront不會這麼快更新,所以要invalidate

aws cloudfront behaviors 設定

其實就是路徑設定相對應的動作
跟 nginx 設path 差不多
所以設錯就不會動
tab(behaviors)=create behavior =>
Forward Headers 如果不要cahce 設定all
Query String Forwarding and Caching <= 傳query string 過去

aws cloudfront Invalidations 強制重抓網站

tab(Invalidations)=> create Invalidations

2017年8月26日 星期六

aws cloudfront ssl 設定

aws cloudfront 只抓的到 us-east-1 的 certificate manager 所設定的憑證喔!

aws cloudfront web設定

edit distruction
Alternate Domain Names
(CNAMEs)
要加domain name (多個的話分行),route 53才抓的到

2017年8月18日 星期五

將line 的chatbot改回對話框!

基本設定
您可在此設定顯示在好友名單、聊天室、主頁的資訊。
公開設定

行動官網選單
顯示 隱藏 儲存
可於聊天室顯示行動官網的選單。 顯示全部

在後台 你去找這個把它設成隱藏


2017年8月1日 星期二

AWS elb + ecs 攻略

https://www.youtube.com/playlist?list=PLimSISlC6rNGdNsstsp9Sn1Cvj9z3oL1Y

ECS mount ebs

ebs mount 後,進shell 關一個 docker container 例如 nginx;
ecs-agent 就會自動全部重啟,
就會認得 mount 的 ebs了

aws ecs ec2 用user data自動mount ebs 上去

應該可以從ecs 裡 綁一個自的 ec2 然後塞 user data 讓他每次 crea
http://docs.aws.amazon.com/AmazonECS/latest/developerguide/bootstrap_container_instance.html
之後再研究

2017年7月25日 星期二

AWS ECS 實作 mongo + mongo-express

https://www.youtube.com/watch?v=3a8xYLU0JgY&feature=youtu.be

AWS ECS 開始入坑筆記。

1.看了一下,去年十月剛推出,我就摸了,還有沒砍的repo,都沒注意到。
2.重摸,順很多,記得剛推出時,有很多靈異狀況都不見了。
3.ECS 主要是將每一個 專案 打包成 Docker Image 上傳到 ECR 上,之後的更新都是以更新 Image 為主。這和 eb (multi-docker)不一樣。
4.eb(multi-docker) 只能在一台機器裡只有1024的memeroy 配置到每一個 docker container 裡,如果只有一堆靜態網站,還ok,但當要操作db時,惡夢就來臨了。
5.原本 db 目錄在 instance 裡,當AWS 偵測到流量 HA 啟動時,會砍舊的instance,自動開新的instance,資料就全沒了。
6.當我開始掛ecs時,我的mongo一直不斷的掛掉,原來是memory不夠。但傻掉,eb只給1024可配置,我的container 還有 ui ...
7.另外不便是 eb create 之後,之前通常可以直接 eb deploy ,但掛 ecs 之後,每次都eb deploy fail.....所以每次都要再 eb create 新主機,也太折騰人。
8.因為問題太多了。另外看ECS經過半年的推出,看起來穩定很多,某默司大神用的很開心,好吧!
開始進入ECS的世界。


2017年7月24日 星期一

找出mongo一直斷線,導致parse-server跟著斷線,導致整個服務中斷的原因

1.發現 multi-docker的 eb 每一次 eb deploy 都會將舊的contianer 砍掉,重新建新的。
2.ebs mount 上去之後,mongo很容易斷線。
mongo很容易斷線的原因是因為mongo container 太小?
還是ebs太大?

3.直接mount node_moudle / 然後減少 ui 的 memory 加到 parse-server 跟 mongo 各256

4. 先 eb create 然後,設定完 https ; email
5.再將 版本丟過去
6.如果出現 Internal Server Error 就console重建吧
因為會重建container故
再進shell重新 service docker restart

2017年7月20日 星期四

aws eb multi-docker with ebs restart

最好先開好兩台機器

1. eb deploy如果動到 Dockerrun.aws.json 很容易導致整個 eb  instance 掛掉,最好先將ebs snapshot 掛在能用的那台eb 然後,所有服務先轉過去,再繼續玩下去。

3.snapshot ebs volume
4.umount 舊的 ebs
5.mount ebs volume:snapshot
6.service docker restart
7.console reboot
不行的話 service docker restart 然後一個一個docker start
sudo docker start $(sudo docker ps -a -q)

8.確定都正常之後,再將服務轉回來



2017年7月18日 星期二

AWS eb 操作良方

一個eb環境
開dev , prod兩個,跟一個 ebs 資料存這裡
eb deploy 只到dev,免得搞掛全部
確認之後
就將版本 部署到 prod
是 需要 重啟 prod (因為ebs mount ; multi-docker 的 eb 會認不到,需要重啟!)





2017年7月17日 星期一

nodejs unzip

s3.getObject({ Bucket: opts.bucket, Key: key }).createReadStream().pipe(unzip.Extract({ path: 'data' }))

2017年7月13日 星期四

2017年7月7日 星期五

punnycode 中文網址 中文網域 轉換

https://www.npmjs.com/package/punycode

2017年6月8日 星期四

2017年5月16日 星期二

website-scraper 好用的爬網站套件

npm install website-scraper

2017年5月7日 星期日

next.j next build失敗 解法

node_module 全部移除 重新安裝
跑一次  node server.js 或 next
再跑 next build
就可以了

解決aws eb multi-docker 資料會被刪除

[最終解法]
eb 只會動 /var/app/current
所以 我直接 mkdir /var/app/db
然後 Dockerrun.aws.json
直接
"volumes": [{
"name": "mongo",
"host": {
"sourcePath": "/var/app/db"
}
}],
這樣就可以了
ebs就沒有很需要了

2017年4月17日 星期一

nginx cache + websocket on AWS single docker

worker_processes 4;

events { worker_connections 1024; }

http {
proxy_cache_path /tmp/cache levels=1:2 keys_zone=cache:30m max_size=1G;

upstream app_upstream {
server localhost:3001;
}

server {
listen 80;

location ~* \.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;

proxy_pass http://app_upstream;
proxy_redirect off;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

location /static {
proxy_cache cache;
proxy_cache_valid 30m;
proxy_pass http://app_upstream;
}

location / {
proxy_cache cache;
proxy_cache_valid 30m;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://app_upstream;
}
}

}

2017年3月20日 星期一

botframewotk locale 設定很特別

export var bot = new builder.UniversalBot(lineConnector, {
    localizerSettings: {
        botLocalePath: __dirname + "/locale",
        defaultLocale: "zh"
    }
});

1. 要注意。tsc 不會自動將 json 引用過去。
2.BotBuilder.json 是 botframework的基礎語言檔 , ex: defualt_number 等,要定義在這裡
3.index.json才是你自已的自定義的 語言檔


2017年3月10日 星期五

docker single docker file on aws nginx setting

FROM node:7.4.0

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
RUN npm install yarn -g
ADD package.json /usr/src/app/package.json
RUN yarn

ENV NGINX_VERSION 1.11.8-1~jessie

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
    && echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y \
                        ca-certificates \
                        nginx=${NGINX_VERSION} \
                        nginx-module-xslt \
                        nginx-module-geoip \
                        nginx-module-image-filter \
                        nginx-module-perl \
                        nginx-module-njs \
                        gettext-base \
    && rm -rf /var/lib/apt/lists/*

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log


# Remove the default Nginx configuration file
RUN rm -v /etc/nginx/nginx.conf

# Copy a configuration file from the current directory
ADD nginx.conf /etc/nginx/

# Append "daemon off;" to the configuration file
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

COPY . /usr/src/app/
CMD service nginx start & npm start;
EXPOSE 80

2017年2月14日 星期二

解 dokcer nodejs "ENOENT: no such file or directory, uv_cwd" issue.

可能是docker 內部的神奇部份,
所以只要 node app.js 跟 node ./app.js or node ../app/app.js
每個docker node 錯開 啟使,就正常了

2017年2月11日 星期六

aws multi docker 心得

每次重啟,每一個docker container 的資料會清空,記得要加上volume到外部的folder,才能保存資料。

Dockerrun.aws.json 的 environment 的設定方式

"environment": [
        {
          "name":"PORT",
          "value":"1337"
        },
        {
          "name":"DATABASE_URI",
          "value":"mongodb://mongo:27017/test"
        },
        {
          "name":"APP_ID",
          "value":"test"
        },
        {
          "name":"MASTER_KEY",
          "value":"test_MASTER_KEY"
        },
        {
          "name":"JAVASCRIPT_KEY",
          "value":"test_JAVASCRIPT_KEY"
        }

     
      ]

2017年2月10日 星期五

aws eb multi docker Dockerrun.aws.json

http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_v2config.html

{
  "AWSEBDockerrunVersion": 2,
  "volumes": [
    {
      "name": "app",
      "host": {
        "sourcePath": "/var/app/current/app"
      }
    },

    {
      "name": "nginx-proxy-conf",
      "host": {
        "sourcePath": "/var/app/current/proxy/conf.d"
      }
    },
    {
      "name": "mongo"
    },
    {
      "name": "parse-server"
    }
  ],
  "containerDefinitions": [
    {
      "name": "app",
      "image": "node:latest",
      "essential": true,
      "memory": 256, //不能太少,會 npm install 失敗
      "command": [
        "/bin/bash",
        "/usr/src/app/run-dev.sh"
      ],
      "portMappings": [
        {
          "hostPort": 3000,
          "containerPort": 3000
        }
      ],
      "mountPoints": [
        {
          "sourceVolume": "app",
          "containerPath": "/usr/src/app"
        }
      ]
    },

    {
      "name":"mongo",
      "image":"mongo",
      "essential": true,
      "memory": 128,
      "portMappings": [
        {
          "hostPort": 27017,
          "containerPort": 27017
        }
      ]

    },
    {
      "name": "parse-server",
      "image": "yongjhih/parse-server",
      "essential": true,
      "memory": 256,
      "portMappings": [
        {
          "hostPort": 1337,
          "containerPort": 1337
        }
      ],
      "mountPoints": [
        {
          "sourceVolume": "app",
          "containerPath": "/usr/src/app"
        }
      ],
      "links": [
        "mongo"
      ],
      "environment": [
        {
          "name":"parse-server",
          "PORT": "1337",
          "DATABASE_URI":"mongodb://mongo:27017/test",
          "APP_ID":"test",
          "MASTER_KEY":"test_MASTER_KEY",
          "JAVASCRIPT_KEY":"test_JAVASCRIPT_KEY"

        }
      ]
    },
 
    {
      "name": "nginx-proxy",
      "image": "nginx",
      "essential": true,
      "memory": 128,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80
        }
      ],
      "links": [
        "parse-server",
        "mongo",
        "app"
      ],
      "mountPoints": [
        {
          "sourceVolume": "awseb-logs-nginx-proxy",
          "containerPath": "/var/log/nginx"
        },
        {
          "sourceVolume": "nginx-proxy-conf",
          "containerPath": "/etc/nginx/conf.d",
          "readOnly": true
        }
      ]
    }

  ]
}

2017年2月8日 星期三

multi docker nginx + nodejs 心得


  1. 用nginx prxoy 可以mapping到不同的image,但外部可以持續用相同的cookie . 
  2. 多專案debug時,直接用內網ip做 proxy_pass就可以了
  3. 用docker-compose做 multi docker,做link後,所有的port都不需要開到外部去,增加安全性.



server {
listen 80;
server_name localhost;
location /test {
proxy_pass http://app:3000/test; # proxy_pass http://192.168.1.100:3000/test;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location / {
proxy_pass http://app2:3001; # proxy_pass http://192.168.1.100:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /parse {
proxy_pass http://parse-server:1337/parse; # proxy_pass http://192.168.1.100:1337/parse;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
} docker-compose.yml <
version: '2'
services:
app:
image: "node:latest"
working_dir: /usr/src/app
command: ./run-dev.sh
volumes:
- ./app:/usr/src/app
environment:
- port=3000
depends_on:
- parse-server
app2:
image: "node:latest"
working_dir: /usr/src/app
command: ./run-dev.sh
volumes:
- ./app:/usr/src/app
environment:
- port=3001
depends_on:
- parse-server
mongo:
image: "mongo"
parse-server:
image: yongjhih/parse-server
# ports:
# - "1337:1337"
environment:
PORT: 1337
DATABASE_URI: "mongodb://mongo:27017/test"
APP_ID: "test"
MASTER_KEY: test_MASTER_KEY
JAVASCRIPT_KEY: test_JAVASCRIPT_KEY
links:
- mongo
depends_on:
- mongo
nginx:
image: nginx
ports:
- "5010:80"
volumes:
- ./proxy/conf.d:/etc/nginx/conf.d
links:
- parse-server
- mongo
- app
- app2