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认证。
原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。