| 知乎專欄 | 多維度架構 | 微信號 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認證。