Nginx+Apache+PHP

18 September 2012


大部分在架設網站的人都會採用LAMP的方式!
就是傳統的Linux+Apache+MySQL+PHP。
但由於這種方式對一般人來說已經是過於簡單了,
甚至已經有一鍵包...只要一直按"下一步"就可以完成安裝...
所以在這就不多做介紹。


在這要介紹一個比較特別的架構叫做LNAMP,
LNAMP和之前的差不多,但多了一個Nginx
Nginx和Apache一樣是web server,
但在這邊我們將在我們的Linux Server上同時安裝二個Web Server(Nginx、Apache)。
然後利用reverse proxy的概念來結合這二個Web Server,


由於Nginx在處理靜態網頁、文件的效能較好,
而Apache一直以來都算是一個穩定的Web Server,但Apache很耗CPU、memory。
但是Nginx並不支援PHP,因此我們可以結合這兩個Web Server的特性來架設我們的網站!



首先先看到下面那張圖,這張圖是我們網站的架構!
我們可以看到圖中的兩個粉紅色區塊,
這兩個區塊都是web server。
而在這邊我會把Nginx的port設為80,
Apache的port改為8080。

當User request http://www.example.com/index.html 的時候,
我們就會透過Nginx response給User!  (就是下圖中左邊的區塊)
但是當User request  http://www.example.com/index.php 的時候,
我們一樣一開始會透過Nginx,可是Nginx會透過reverse proxy的機制,
reverse給Apache進行處理!!!  (就是下圖中右邊的區塊)



透過上圖中的機制可以有效的快速response user,
也可以減輕Server的負擔!
甚至可以減輕MySQL的負擔!
記得以前在某公司當intern的時候,
由於該公司的某項服務在當時似乎是國內前幾大的,
然後他們某項服務就是利用rewrite的概念,盡量不會有Dynamic Page,
他們系統每一陣子會把Dynamic Page的內容rewite成一個Static Page,
這樣他們的User都會去request 該Static Page,
而不會去request Dynamic Page,同時也減輕了DB的負擔!


講完架構以後,
接著要教大家怎麼把Nginx+Apache同時架起來!
我的環境是Ubuntu,
在這我就不教大家怎麼install Apahce和PHP了...應該是common sense!

進行說明設定Nginx之前,
如果你已經將Apache安裝起來了,那請先把你的Apache port改成8080。
因為Nginx等等會使用80。


完成上述步驟,就來安裝Nginx,
sudo apt-get install nginx

安裝完成以後,如果你去request自己網站底下的某隻.php
例如:www.example.com/index.php
那麼是跑不起來的,因為Nginx並不支援任何的Dynamic Language(php, perl, jsp...etc)
所以要把有關Dynamic Page的任何request reverse proxy至apache去!


所以就要進行設定,首先要把nginx的port改為80
cd /etc/nginx/sites-available  #先切換至nginx的設定目錄底下
sudo vim default #修改設定檔

打開設定檔以後,記得在Server{}裡面加入下面的設定,

listen 80 #預設是mark起來的,把最前面的#號拿掉就好,如果沒有這行就自己加吧!

# 下面這段的意思是,當遇到.php檔名的就把它轉向至8080
location ~ \.php$ {
proxy_pass http://127.0.0.1:8080;
}

上面的設定主要就是過濾掉.php,
把php通通交給apache進行處理,
當然你也可以做更細部的過濾設定,
例如.jpg、.css、.js等等之類的靜態檔案都cached起來,
不要進行不必要的request。
例如
location ~* \.(jpg|png)$ {
expires 30d; # cached 30天的意思
}


完成上面的設定以後,
就將Nginx重開吧!
sudo /etc/init.d/nginx restart



基本上重開以後,應該就完成LNAMP的架構了!





read more »


使用Google OAuth 2.0 存取Google API

15 September 2012

這篇文章主要是教學如何使用Google OAuth,
然後利用OAuth給的token去存取gmail帳號!


至於OAuth是甚麼就不多做介紹...
可以去WIKI看  http://en.wikipedia.org/wiki/OAuth
簡言之,是一個公開的標準認證機制!


而使用Google OAuth大概可以分為下列步驟:

  1. 在Google Console註冊一個Application 
  2. 取得Google回傳的Access Token(基本上到這步驟,代表登入成功)
  3. 傳送Access Token至某隻Google API取得Google的資料


【在Google Console註冊一個Application 】

在這步驟要先去Google Console頁面上去註冊一個application,
然後再為這個application申請一組client id。


首先要先去這個站(https://code.google.com/apis/console/b/0/#project:1007457656912:access),
點進去以後大概會見到下圖,
見到下圖(圖一)以後,就先點選下圖(圖一)中左邊的API Access,
注意! 一定要點! 點了以後,下圖(圖一)中右邊的區塊才會出現Create an OAuth 2.0 client ID的按鈕!
出現右邊的區塊以後,就點選Create an OAuth 2.0 client ID的按鈕!
圖一


如果你曾經註冊過一個application,那就不會看到上圖(圖一)的頁面,
但大同小異! 還是會有一個按鈕(Create another client ID...)
點選以後就會直接見到圖三,而不會見到下圖(圖二)

而如果沒有註冊過application的,就會見到下圖(圖二)。
下面的頁面主要輸入產品名稱即可! 
輸入以後就按下下圖(圖二)Next

圖二



點選上圖(圖二)中的Next以後,就會見到下圖(圖三),
這個頁面很重要!
這頁面要填寫你的Domain Name以及接收access token的頁面!
但預設的狀況你只能填寫Domain Name,如下圖(圖三)的紅色框框!
而藍色框框中的URI(https://www.example.com/oauth2callback) 就是接收access token的頁面!
當然,如果你想要填寫自己接收access token的頁面,也是可以自己改!
只要點選下圖(圖三)中的綠色框框(more options)即可!
點選以後就會見到下圖(圖四)
圖三


下圖(圖四)就是點選上圖(圖三)的more options才會看到的頁面。
你可以看到下圖(圖四)有個紅色框框,在那裏面就可以修改自己接收access token的頁面!
填寫完成以後,記得按下圖片中(圖三或圖四)下面的Create client ID按鈕!
點了才會完成。

圖四

完成以後,會看到下圖(圖五)的頁面!
這頁面也很重要!!!!
因為Google 會給你一組Client ID和Client Sercet,
這兩個資訊在後面進行auth的時候會用到!
圖五


【取得Google回傳的access token 】

在這步驟就要進行coding了。
詳細的說明文件可以參考(https://developers.google.com/accounts/docs/OAuth2Login)


先大致說明一下流程,可以參考下圖。
流程一:
  User會先點選一個URL,
  而這URL會連結至Google 登入頁面,
  User得先輸入帳號&密碼進行登入,
  (這過程都是在Google Server上進行,我們的Server端是不會取得到User的密碼的)
流程二:
  如果User輸入的帳號密碼正確,那麼Google就會把Access Token傳回去至我們的Server,
流程三:
  發一個request給Google API,
  把Google回傳給我們的token傳至Google API以存取我們想要存取的資訊!
流程三:
  接收Google 回傳的資訊



恩,接著要開始寫code了。
如上面所述,我們要有一個接收access token的頁面!
以及一個讓User點擊的連結(這個連結會redirect至Google登入頁面)
而這個連結也會帶著幾個參數!
如下


使用Google登入



參數說明:
scope:意思是你要利用這個token存取那些Google API,這邊我們要存取USER資訊,所以就是如上述sample所示。
state:這是一個optional 的參數,可以填任意字串
redirecut_uri:這個參數很重要,意思是如果user輸入帳密正確以後,Google要redirect至哪一個接收access_token的頁面,基本上這個參數的value就是如上圖中(圖四)你所填的值!
response_type:這個參數的value一定要填寫code!code的意思是我們接收的頁面是用server-side接收response! 預設還有另一個value(token),但token代表的是我們是利用Javascript去進行接收!但此sample是用JSP/Servlet的Servlet來接收!所以就填寫code!
client_id:就填寫自己的client_id!!!

基本上user點選上述的Link以後,
會見到登入頁面!
登入完成以後就會redirect至oauth2callback去了!
並且會reponse一個參數給我們!參數名稱為code

而這邊我已JSP/Servlet為例!
所以我先建立一個名字為oauth2callback的Servlet,
這個Servlet會用來接收Google回傳給我們的參數(code),
然後這支Servlet會再發出一個request,並且帶著參數code。
然後Google就會回傳給我們access_token

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

// Google取得access_token的url
URL urlObtainToken = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection connectionObtainToken = (HttpURLConnection) urlObtainToken.openConnection();

// 設定此connection使用POST
connectionObtainToken.setRequestMethod("POST");
connectionObtainToken.setDoOutput(true);

// 開始傳送參數
OutputStreamWriter writer = new OutputStreamWriter(connectionObtainToken.getOutputStream());
writer.write("code="+req.getParameter("code")+"&"); // 取得Google回傳的參數code
writer.write("client_id=xxxxxxxxxxxxxxxxxx&xxxx&"); // 這裡請將xxxx替換成自己的client_id
writer.write("client_secret=xxxxxxxxxxxxxxxxxxx&"); // 這裡請將xxxx替換成自己的client_serect
writer.write("redirect_uri=xxxxxxxxxxxxxxxxxxxx&"); // 這裡請將xxxx替換成自己的redirect_uri
writer.write("grant_type=authorization_code");
writer.close();

// 如果認證成功
if (connectionObtainToken.getResponseCode() == HttpURLConnection.HTTP_OK){
StringBuilder sbLines = new StringBuilder("");

// 取得Google回傳的資料(JSON格式)
BufferedReader reader =
new BufferedReader(new InputStreamReader(connectionObtainToken.getInputStream(),"utf-8"));
String strLine = "";
while((strLine=reader.readLine())!=null){
sbLines.append(strLine);
}

try {
// 把上面取回來的資料,放進JSONObject中,以方便我們直接存取到想要的參數
JSONObject jo = new JSONObject(sbLines.toString());

// 印出Google回傳的access token
resp.getWriter().println(jo.getString("access_token"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}







如果完成上述步驟,基本上就代表user的帳號密碼是正確!
那意思就是說,如果你的網站想要導入讓user使用Google帳號進行登入的話,
完成上述步驟就OK了!

當然,如果你想要取得更進一步的user資訊,
只要利用上述得到的access_token,然後把這個token帶給Google API即可獲得資訊!
例如想要得到User的email,即可利用下列的API,
https://www.googleapis.com/oauth2/v1/userinfo
但是要餵給他參數!
CODE如下:


URL urUserInfo =   
new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="+jo.getString("access_token"));
HttpURLConnection connObtainUserInfo = (HttpURLConnection) urUserInfo.openConnection();


//如果認證成功
if (connObtainUserInfo.getResponseCode() == HttpURLConnection.HTTP_OK){
StringBuilder sbLines = new StringBuilder("");

// 取得Google回傳的資料(JSON格式)
BufferedReader reader =
new BufferedReader(new InputStreamReader(connObtainUserInfo.getInputStream(),"utf-8"));
String strLine = "";
while((strLine=reader.readLine())!=null){
sbLines.append(strLine);
}

try {
// 把上面取回來的資料,放進JSONObject中,以方便我們直接存取到想要的參數
JSONObject jo = new JSONObject(sbLines.toString());

// 印出Google回傳的"emailtoken
resp.getWriter().println(jo.getString("email"));

} catch (JSONException e) {
e.printStackTrace();
}
}






read more »


Arduino 基本教學

28 July 2012

Arduino 是一塊Open Source電路板,
開發者可以利用這塊板子去做到一些電子器材的控制,
例如:開燈、關燈,甚至可以在Arduino上裝上sensor,
然後根據sensor的資料來做處理!例如接上了光敏電阻這個sensor,
我們就可以判斷目前光的亮度,就可以根據不同亮度做不同的回應。
詳細資料可以去官網看:http://arduino.cc/en/


這篇主要教大家怎麼寫一個簡單的應用,
在後面會教大家怎麼接上藍芽模組,然後透過無線的方式和Arduino溝通!
基本上要做到下列的事項

  1. 購買Arduino電路板
  2. 下載Arduino IDE開發工具
  3. 在電腦上安裝Arduino的Driver
  4. 寫個簡單應用並部屬上去Arduino

【第一步、購買Arduino】
在開發前,大家一定要有一塊Arduino電路板,
基本上在Y拍就買得到了,一塊基本的價格大概在600~1000左右!
因為其實Arduino板子有分很多種,且有的還算是加強版!
但都大同小異。
我買的板子是Duemilanove版本,如圖!


【第二步、下載Arduino IDE】
接著得去下載開發工具,
才能寫程式,並燒到Arduino上面去。
下載網址:http://arduino.cc/en/Main/Software
下載下來以後,就解壓縮出來即可。



【第三步、安裝Driver】
接著把Arduino接上電腦,如下圖,
基本上你的電腦應該找不到Driver,
這時候就【我的電腦點選右鍵】→【點選管理】→【點選裝置管理員】
基本上應該就會看到無法辨識的設備,
在該設備上點選右鍵,選擇內容。
然後接著就自己去尋找Driver的路徑,
而Driver就在第二步下載下來的檔案當中,
在解壓縮出來的資料夾當中\arduino-1.0.1\drivers。
安裝完成以後,請記得自己的Serial Port!!(像我的就是21,如下圖)
因為等等會透過此Port把程式燒進去。



【第四步、寫個應用】
首先先打開Arduino IDE,
就在第二步中解壓縮的資料夾當中,
檔名為arduino.exe。
打開以後會見到下圖。
而白色的區塊就是你可以寫code的地方。


接著得點選Tool→Board,如下圖
先選擇你購買的Arduino電路板版本,像我是Duemilanove,
所以就選這個!
如果你選錯,基本上是無法upload到Arduino板子上去的!

接著就選擇第三步中的Serial Port,像我是21,所以就選21,
如下圖。



接著就可以開始寫程式了,
首先我先說明一下,基本上你們購買的Arduino板子上,
一定會有一個小小的LED燈,
而這LED燈是連接到pin腳為13的pin上。如下圖


而我們現在就要寫一個程式去開關該led燈。
CODE如下:
// 先宣告Pin腳位置
int iPinLed = 13;
void setup() {
// 宣告該Pin腳是output
pinMode(iPinLed, OUTPUT);
}
void loop() {
// 開始寫資料,寫HIGH進去就是讓它亮
digitalWrite(iPinLed, HIGH);
delay(1000);
 // 寫LOW進去就是讓它暗
digitalWrite(iPinLed, LOW);
delay(1000);
}

基本上Arduino的程式分了兩個區塊

  1. setup
  2. loop
setup就是傳統的main,也可以想成是constructor,
loop就是會一直執行的部分,可以想成for迴圈。
而上述的程式中,我們先宣告了一個整數(iPinLed),代表pin腳的位置,
接著在setup中把它宣告成是做輸出的動作,也就是說我們會透過這個pin腳餵資料給led
然後就進入loop,第一行就是讓led變亮,
接著就delay一秒鐘,
之後又把led關掉。
又停了一秒。
不斷的重複上述步驟。
而程式的結果如下列影片。
LED燈會一閃一閃的!





 從上述的例子來看或許有點過於單調,
但就像本文一開始所說的,
Arduino可以接上許多裝置,然後透過Arduino控制該裝置。
像此文就是透過Arduino去控制單一LED。
你可以想像如果你有一百顆LED,你也可以通通接上 Arduino ,
然後透過Arduino去控制那一百顆LED。

然後在後面的文章將會介紹怎麼透過Arduino去控制機器手臂。













read more »