知乎專欄 | 多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者” |
SOA 與 REST很多相同之處,目前SOA主要是基于SOAP實現,也有基于MQ的實現。而REST只限于HTTP POST/GET/PUT/DELETE等等。
我個人比較喜歡機遇TCP的SOA實現,不喜歡SOAP大量XML傳輸。
這裡提供一個簡單的機遇SOAP實現的SOA框架
index.php入口檔案
<?php define ('CONFIG_DIR', '../config/'); define ('LIBRARY_DIR', '../library/'); define ('DEBUG', false); //define ('DEBUG', ture); require_once(CONFIG_DIR. 'default.php'); $remote_addr = $_SERVER['REMOTE_ADDR']; if(!in_array($remote_addr, $firewall)) { printf("Permission denied: %s", $remote_addr); exit(0); } $request_uri = $_SERVER['REQUEST_URI']; $classspath = LIBRARY_DIR.strtolower($request_uri) . '.class.php'; if( is_file($classspath) ){ require_once($classspath); }else{ die("Cannot loading interface!"); } $class = ucfirst(substr($request_uri, strrpos($request_uri, '/')+1)); if( DEBUG ){ printf("%s<br>",$class); } if (class_exists($class)) { $server = new SoapServer(null, array('uri' => "http://webservice.example.com")); $server->setClass($class); $server->handle(); }else{ die('Object isnot exist.'); }
介面檔案
<?php require_once('common.class.php'); class Members extends Common{ private $dbh = null; public function __construct() { parent::__construct(); $this->dbh = new Database('slave'); } public function getAllByUsernameAndMobile($username,$mobile){ $result = array(); if(empty($username) or empty($mobile)){ return($result); } $sql = "SELECT username, chinese_name, sex FROM members m, members_digest md WHERE m.id = md.id and m.username= :username and md.mobile = md5( :mobile );"; $stmt = $this->dbh->prepare($sql); $stmt->bindValue(':username', $username); $stmt->bindValue(':mobile', $mobile); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return($result); } public function getAllByLimit($limit,$offset) { $sql = "SELECT username FROM members limit ".$limit.",".$offset; $stmt = $this->dbh->query($sql); while ($row = $stmt->fetch()) { //printf("%s\r\n", $row['username']); $result[] = $row['username']; } return $result; } function __destruct() { $this->dbh = null; } }
客戶端調用實例
<?php $options = array('uri' => "http://webservice.example.com", 'location'=>'http://webservice.example.com/members', 'compression' => 'SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP', 'login'=>'neo', 'password'=>'chen', 'trace'=>true ); $client = new SoapClient(null, $options); try { print_r($client->getAllByUsernameAndMobile('280600086','13113668890')); print_r($client->getAllByLimit(20,20)); } catch (Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; }
Nginx 虛擬主機配置檔案 /etc/nginx/conf.d/webservice.example.com.conf
server { listen 80; server_name webservice.example.com; charset utf-8; access_log /var/log/nginx/webservice.example.com.access.log main; auth_basic "Login"; auth_basic_user_file htpasswd; location / { root /www/example.com/webservice.example.com/htdocs; index index.html index.php; if ($request_filename !~ (js|css|images|robots/.txt|.*\.html|index/.php) ) { rewrite ^/(.*)$ /index.php/$1 last; break; } } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ /index.php/ { root /www/example.com/webservice.example.com/htdocs; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/example.com/webservice.example.com/htdocs$fastcgi_script_name; include fastcgi_params; } }
每增加一個功能需求,在library中創建一個 Class 檔案即可。
index.php 有IP過濾功能,禁止非法IP訪問
客戶端採用壓縮傳輸,節省xml傳輸開銷
Nginx 設置了HTTP認證,防止他人探測,另外提示你還可以採用雙向SSL認證。