SOA 面向服务框架设计与实现
时间:2022-05-03
本文章向大家介绍SOA 面向服务框架设计与实现,主要内容包括14.4. Service-oriented architecture (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("%srn", $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
- spring cloud 学习(6) - zuul 微服务网关
- ES6 Features系列:Template Strings & Tagged Template Strings
- 基于Tcp协议的简单Socket通信实例(JAVA)
- spring集成kafka
- Java常用类(二)String类详解
- 用树莓派玩转蓝牙
- CSS魔法堂:你真的理解z-index吗?
- HashSet
- 树莓派的GPIO编程
- Java集合源码分析(三)Vevtor和Stack
- JS魔法堂:再识instanceof
- Web开发之CSS
- Linux重启命令与如何重启网络?
- spring boot + embed tomcat + standalone jar的内存泄露问题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- reduce学习笔记
- 【python实现卷积神经网络】开始训练
- django实战(五)--增加数据
- 实战django(一)--(你也能看懂的)注册与登录(带前端模板)
- 【python-leetcode23-多路归并】合并k个排序链表
- 实战django(二)--登录实现记住我
- org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.gong.mybatis.da
- 【python-leetcode378-二分查找】有序矩阵中的第k小元素
- 使用cookie来记录用户登录次数,为何次数不更新
- (二)golang--windows下vscode的安装以及go环境的配置
- mybatis文件映射之使用#取值时的一些规则
- 【论文笔记】Improved Residual Networks for Image and Video Recognition(ResNet新变体:IResNet)
- SQL语句在MYSQL中的运行过程和各个组件的介绍
- (五)golang--常用的一些玩意
- 关于MYSQL 的日志系统