Authored by 郝肖肖

分流从memcache中获取

... ... @@ -12,6 +12,8 @@
namespace Api;
use Plugin\Cache;
use Plugin\UdpLog;
class Yohobuy
{
... ... @@ -153,13 +155,20 @@ class Yohobuy
$urlBack = $url;
if (USE_INTER_FACE_SHUNT) {
if (strpos($url, 'api.')) {
if (strpos($url, 'api')) {
$isApi = true;
$url = self::_getUrl($url, $data);
} else if (strpos($url, 'service.')) {
} else if (strpos($url, 'service')) {
$isService = true;
$url = self::_getUrl($url, $data);
}
//$url 返回为空,走原先的url
if (empty($url)) {
$isApi = false;
$isService = false;
$url = $urlBack;
}
}
// 销毁私钥参数
... ... @@ -171,6 +180,8 @@ class Yohobuy
$url = self::httpBuildQuery($url, $data);
} //echo $url;
UdpLog::debug('get shut api', $url);
/* 开启缓存的情况 */
if ($cache && USE_CACHE) {
// 先尝试获取一级缓存(master), 有数据则直接返回.
... ... @@ -265,6 +276,8 @@ class Yohobuy
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
}
UdpLog::debug('call api: ', $url);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
if (!$returnJson && !empty($result)) {
... ... @@ -306,13 +319,20 @@ class Yohobuy
$urlBack = $url;
if (USE_INTER_FACE_SHUNT) {
if (strpos($url, 'api.')) {
if (strpos($url, 'api')) {
$isApi = true;
$url = self::_getUrl($url, $data);
} else if (strpos($url, 'service.')) {
} else if (strpos($url, 'service')) {
$isService = true;
$url = self::_getUrl($url, $data);
}
//$url 返回为空,走原先的url
if (empty($url)) {
$isApi = false;
$isService = false;
$url = $urlBack;
}
}
$ch = curl_init($url);
... ... @@ -353,6 +373,9 @@ class Yohobuy
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
UdpLog::debug('post api', array('url' => $url, 'httpCode' => $httpCode));
//如果分流执行失败,则走原来的逻辑
if (USE_INTER_FACE_SHUNT && $httpCode !== 200) {
curl_close($ch);
... ... @@ -399,6 +422,9 @@ class Yohobuy
//curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
}
UdpLog::debug('post fail api', $url);
$result = curl_exec($ch);
if (!$returnJson && !empty($result)) {
$result = json_decode($result, true);
... ... @@ -678,10 +704,21 @@ class Yohobuy
*/
private static function _getUrl($url, $param)
{
if (USE_INTER_FACE_SHUNT === false) {
return $url;
if (USE_CACHE === false || USE_INTER_FACE_SHUNT === false) {
return false;
}
UdpLog::debug('read memcache');
$interfaceShunt = Cache::getBy('INTERFACE_SHUT_KEY', 'master');
UdpLog::debug('read memcahe: ', $interfaceShunt);
if (empty($interfaceShunt)) {
return false;
}
$interfaceShunt = json_decode($interfaceShunt, true);
$uid = 0;
$mod = 0;
... ... @@ -691,20 +728,67 @@ class Yohobuy
}
if ($mod > 128 || $uid === 0) {
$paseUrl = parse_url($url);
if (strpos($url, 'api.')) {
$url = 'http://' . self::$interfaceShunt['awsServers']['api'] . rtrim($paseUrl['path'], '/') . '/';
} else if (strpos($url, 'service.')) {
$url = 'http://' . self::$interfaceShunt['awsServers']['service'] . rtrim($paseUrl['path'], '/') . '/';
if (strpos($url, 'api')) {
if (empty($interfaceShunt['aws']) || empty($interfaceShunt['aws']['api.yoho.cn'])) {
return false;
}
$num = array_rand($interfaceShunt['aws']['api.yoho.cn']);
if (empty($interfaceShunt['aws']['api.yoho.cn'][$num]['ip'])) {
return false;
}
$url = 'http://' . $interfaceShunt['aws']['api.yoho.cn'][$num]['ip'] . rtrim($paseUrl['path'], '/') . '/';
} else if (strpos($url, 'service')) {
if (empty($interfaceShunt['aws']) || empty($interfaceShunt['aws']['service.yoho.cn'])) {
return false;
}
$num = array_rand($interfaceShunt['aws']['service.yoho.cn']);
if (empty($interfaceShunt['aws']['service.yoho.cn'][$num]['ip'])) {
return false;
}
$url = 'http://' . $interfaceShunt['aws']['service.yoho.cn'][$num]['ip'] . rtrim($paseUrl['path'], '/') . '/';
}
} else {
$paseUrl = parse_url($url);
if (strpos($url, 'api.')) {
$num = array_rand(self::$interfaceShunt['tencentServers']['api']);
$url = 'http://' . self::$interfaceShunt['tencentServers']['api'][$num] . rtrim($paseUrl['path'], '/') . '/';
} else if (strpos($url, 'service.')) {
$num = array_rand(self::$interfaceShunt['tencentServers']['service']);
$url = 'http://' . self::$interfaceShunt['tencentServers']['service'][$num] . rtrim($paseUrl['path'], '/') . '/';
if (strpos($url, 'api')) {
if (empty($interfaceShunt['tencent']) || empty($interfaceShunt['tencent']['api.yoho.cn'])) {
return false;
}
$num = array_rand($interfaceShunt['tencent']['api.yoho.cn']);
if (empty($interfaceShunt['tencent']['api.yoho.cn'][$num]['ip'])) {
return false;
}
$url = 'http://' . $interfaceShunt['tencent']['api.yoho.cn'][$num]['ip'] . rtrim($paseUrl['path'], '/') . '/';
} else if (strpos($url, 'service')) {
if (empty($interfaceShunt['tencent']) || empty($interfaceShunt['tencent']['service.yoho.cn'])) {
return false;
}
$num = array_rand($interfaceShunt['tencent']['service.yoho.cn']);
if (empty($interfaceShunt['tencent']['service.yoho.cn'][$num]['ip'])) {
return false;
}
$url = 'http://' . $interfaceShunt['tencent']['service.yoho.cn'][$num]['ip'] . rtrim($paseUrl['path'], '/') . '/';
}
}
... ...
<?php
namespace Plugin;
use Hood\Cache as HoodCache;
/**
* 数据缓存的操作类
*
* @name Cache
* @package Plugin
* @copyright yoho.inc
* @version 1.0 (2015-10-10 11:23:47)
* @author fei.hong <fei.hong@yoho.cn>
*/
class Cache
{
/**
* 设置缓存
*
* 备注:
* 采用主从分布式缓存
* master 代表主缓存服务器
* slave 代表从缓存服务器
*
* 作用:
* 在后端的服务异常挂掉了并且主服务器缓存(master)的数据时间到期后,
* 能获取从服务器缓存(slave)的数据,不影响前端页面的正常访问.
*
* @param string $key 键名
* @param mixed $value 需要缓存的数据
* @param int $expire 缓存有效期(单位秒, 0表示永久)
* @return void
*/
public static function set($key, $value, $expire = 300)
{
try {
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
HoodCache::Memcache('master')->set(self::makeKey($key, 'master'), $value, $expire);
HoodCache::Memcache('slave')->set(self::makeKey($key, 'slave'), $value, 86400); // 二级缓存1天
}
// LINUX
else {
HoodCache::Memcached('master')->set(self::makeKey($key, 'master'), $value, $expire);
HoodCache::Memcached('slave')->set(self::makeKey($key, 'slave'), $value, 86400); // 二级缓存1天
}
} catch (Exception $e) {
// do nothing
}
}
/**
* 获取缓存
*
* @param string $key 键名
* @param string $node master代表主服务器, slave代表从服务器
* @return mixed
*/
public static function get($key, $node = 'master')
{
$result = array();
try {
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
$result = HoodCache::Memcache($node)->get(self::makeKey($key, $node));
}
// LINUX
else {
$result = HoodCache::Memcached($node)->get(self::makeKey($key, $node));
}
// 当接口异常,一级缓存没取到数据的情况
if ($node === 'slave') {
$incrementKey = self::makeKey('_increment_' . $key, 'slave');
$incrementValue = HoodCache::Memcached('slave')->get($incrementKey);
// 接口调用失败累计5次之后,回填二级缓存数据到一级缓存, 重置计数值为0
if (is_int($incrementValue) && $incrementValue > 5) {
HoodCache::Memcached('master')->set(self::makeKey($key, 'master'), $result, 300);
HoodCache::Memcached('slave')->set($incrementKey, 0, 3600);
}
// 接口调用失败次数累加
else {
HoodCache::Memcached('slave')->increment($incrementKey, 1, 0, 3600);
}
}
} catch (Exception $e) {
$result = array();
}
return $result;
}
/**
* 清除缓存
*
* @param string $key 键名
* @return void
*/
public static function delete($key)
{
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
HoodCache::Memcache('master')->delete(self::makeKey($key, 'master'));
HoodCache::Memcache('slave')->delete(self::makeKey($key, 'slave'));
}
// LINUX
else {
HoodCache::Memcached('master')->delete(self::makeKey($key, 'master'));
HoodCache::Memcached('slave')->delete(self::makeKey($key, 'slave'));
}
}
/**
* 累加
*
* @param string $key
* @param int $offset
* @param int $initialValue
* @param int $expiry
* @return boolean
*/
public static function increment($key, $offset = 1, $initialValue = 0, $expiry = 0)
{
return HoodCache::Memcached('master')->increment(self::makeKey($key, 'master'), $offset, $initialValue, $expiry);
}
/**
* 递减
*
* @param string $key
* @param int $offset
* @return boolean
*/
public static function decrement($key, $offset = 1)
{
return HoodCache::Memcached('master')->decrement(self::makeKey($key, 'master'), $offset);
}
/**
* 生成键名
*
* @param string $key 键名
* @param string $prefix 前缀标识
* @return string
*/
public static function makeKey($key, $prefix)
{
return md5($prefix . '_' . $key);
}
}
<?php
namespace Plugin;
use Hood\Cache as HoodCache;
/**
* 数据缓存的操作类
*
* @name Cache
* @package Plugin
* @copyright yoho.inc
* @version 1.0 (2015-10-10 11:23:47)
* @author fei.hong <fei.hong@yoho.cn>
*/
class Cache
{
/**
* 设置缓存
*
* 备注:
* 采用主从分布式缓存
* master 代表主缓存服务器
* slave 代表从缓存服务器
*
* 作用:
* 在后端的服务异常挂掉了并且主服务器缓存(master)的数据时间到期后,
* 能获取从服务器缓存(slave)的数据,不影响前端页面的正常访问.
*
* @param string $key 键名
* @param mixed $value 需要缓存的数据
* @param int $expire 缓存有效期(单位秒, 0表示永久)
* @return void
*/
public static function set($key, $value, $expire = 300)
{
try {
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
HoodCache::Memcache('master')->set(self::makeKey($key, 'master'), $value, $expire);
HoodCache::Memcache('slave')->set(self::makeKey($key, 'slave'), $value, 86400); // 二级缓存1天
}
// LINUX
else {
HoodCache::Memcached('master')->set(self::makeKey($key, 'master'), $value, $expire);
HoodCache::Memcached('slave')->set(self::makeKey($key, 'slave'), $value, 86400); // 二级缓存1天
}
} catch (Exception $e) {
// do nothing
}
}
/**
* 获取缓存
*
* @param string $key 键名
* @param string $node master代表主服务器, slave代表从服务器
* @return mixed
*/
public static function get($key, $node = 'master')
{
$result = array();
try {
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
$result = HoodCache::Memcache($node)->get(self::makeKey($key, $node));
}
// LINUX
else {
$result = HoodCache::Memcached($node)->get(self::makeKey($key, $node));
}
// 当接口异常,一级缓存没取到数据的情况
if ($node === 'slave') {
$incrementKey = self::makeKey('_increment_' . $key, 'slave');
$incrementValue = HoodCache::Memcached('slave')->get($incrementKey);
// 接口调用失败累计5次之后,回填二级缓存数据到一级缓存, 重置计数值为0
if (is_int($incrementValue) && $incrementValue > 5) {
HoodCache::Memcached('master')->set(self::makeKey($key, 'master'), $result, 300);
HoodCache::Memcached('slave')->set($incrementKey, 0, 3600);
}
// 接口调用失败次数累加
else {
HoodCache::Memcached('slave')->increment($incrementKey, 1, 0, 3600);
}
}
} catch (Exception $e) {
$result = array();
}
return $result;
}
/**
* 直接查询缓存,不对key做任何处理
*/
public static function getBy($key, $node = 'master')
{
$result = array();
try {
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
$result = HoodCache::Memcache($node)->getBy($key);
}
// LINUX
else {
$result = HoodCache::Memcached($node)->getBy($key);
}
} catch (Exception $e) {
$result = array();
}
return $result;
}
/**
* 清除缓存
*
* @param string $key 键名
* @return void
*/
public static function delete($key)
{
// WINDOWS
if (DIRECTORY_SEPARATOR === '\\') {
HoodCache::Memcache('master')->delete(self::makeKey($key, 'master'));
HoodCache::Memcache('slave')->delete(self::makeKey($key, 'slave'));
}
// LINUX
else {
HoodCache::Memcached('master')->delete(self::makeKey($key, 'master'));
HoodCache::Memcached('slave')->delete(self::makeKey($key, 'slave'));
}
}
/**
* 累加
*
* @param string $key
* @param int $offset
* @param int $initialValue
* @param int $expiry
* @return boolean
*/
public static function increment($key, $offset = 1, $initialValue = 0, $expiry = 0)
{
return HoodCache::Memcached('master')->increment(self::makeKey($key, 'master'), $offset, $initialValue, $expiry);
}
/**
* 递减
*
* @param string $key
* @param int $offset
* @return boolean
*/
public static function decrement($key, $offset = 1)
{
return HoodCache::Memcached('master')->decrement(self::makeKey($key, 'master'), $offset);
}
/**
* 生成键名
*
* @param string $key 键名
* @param string $prefix 前缀标识
* @return string
*/
public static function makeKey($key, $prefix)
{
return md5($prefix . '_' . $key);
}
}
... ...