SOA 面向服务框架设计与实现

文章节选自 《Netkiller Architect 手札》

由于Java 语言的编译与重启不可抗拒缺陷,所选择使用PHP弥补这个缺陷。

在合适的场景中使用PHP 为 Java 提供 SOA 服务有很多优势,最大的优势就是升级,能够随时升级,即时生效,服务不中断。

任何一种语言都有其擅长的一面,多种语言互补是一种趋势。

14.4. Service-oriented architecture (SOA)

SOA 与 REST很多相同之处,目前SOA主要是基于SOAP实现,也有基于MQ的实现。而REST只限于HTTP POST/GET/PUT/DELETE等等。

我个人比较喜欢机遇TCP的SOA实现,不喜欢SOAP大量XML传输。

14.4.1. SOAP实现

这里提供一个简单的机遇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认证。

有兴趣可以看看这个项目:

https://github.com/netkiller/SOA

原文发布于微信公众号 - Netkiller(netkiller-ebook)

原文发表时间:2016-09-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

不能轻视的mysql重启过程 (r7笔记第55天)

数据库的重启看似是一件非常简单,没有技术含量的活,这是我以前说的话。而这句话简直是戳中了我的痛点。这种活真是太有技术含量了,高深到让人需要注意太多的东西,需要做...

3365
来自专栏挖坑填坑

ABP框架学习之——授权(Authorization)

571
来自专栏我叫刘半仙

原分布式系统架构实战demo:SSM+Dubbo

        对于传统的单一构架,也就是打成的war或者ear包部署在同一个Web容器里的构架,它虽然开发、测试、部署简单,但随着业务的不断发展,维护成本增加...

8077
来自专栏Golang语言社区

社区leaf学习笔记|03. 调试Game、Login模块收发消息

772
来自专栏Golang语言社区

Go HttpServer 最佳实践

这是 Cloudflare 的 Filippo Valsorda 2006年发表在Gopher Academy的一篇文章, 虽然过去两年了,但是依然很有意义。

1270
来自专栏向治洪

如何让service不被杀死

1.在service中重写下面的方法,这个方法有三个返回值, START_STICKY是service被kill掉后自动重写创建 @Override    ...

1557
来自专栏大魏分享(微信公众号:david-share)

从一张图看Devops全流程

一、持续交付工具链全图 ? 上图源自网络。上图很清晰地列出了CD几个阶段使用的工具。 CD的工具链很长,但并不是每个模块所有工具都那么流行;换言之,我们在每个模...

9079
来自专栏C/C++基础

CUDA编译器nvcc的用法用例与问题简答

本文使用nvcc版本:Cuda compilation tools, release 5.5, V5.5.0

612
来自专栏杨建荣的学习笔记

11g备库搭建碰到自己给自己埋的坑(r7笔记第63天)

记得之前在《一半技术一半生活》中分享过一个设计,因为业务的需求,为了提高业务的处理效率,采用了根据业务的拆库拆表的方式,类似下面的图示。 ? 开发团队也很给...

3425
来自专栏FreeBuf

网站管理软件 – AspxSpy2014 Final

受bin牛委托修改并发布,版权归bin牛所有。 Bug/建议提交:zcgonvh@rootkit.net.cn 祝各位马年大吉,财源滚滚。 免责声明: 本程序只...

2019

扫码关注云+社区