kvflush.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. namespace loyalsoft;
  3. include_once __DIR__ . '/../../main.php';
  4. require_once ROOTDIR . '/util/OpenSSLVerify.php'; # Ps. 这个文件和类名没有对应关系.
  5. /**
  6. * Description of config
  7. * 数据中转功能.
  8. * 通过远程地址向服务器刷入Cmem的key-value数据. key和value通过gzcompress和base64处理.
  9. * @version
  10. * 2.0.0 增加了将数据写入到PHP文件的功能(CodeGen_Folder),配合客户端生成的读取代码,可以避免从
  11. * redis中获取数据, 而是直接从代码中获取数据, 在有代码缓存的情况下,
  12. * 相当于直接使用内存中的数据, 节省了与redis的网络通讯时间(平均单次数据获取>1ms),
  13. * 如果一段代码中使用到的配置数据比较多, 那么节省的时间消耗相当明显. -gwang 2020.11.27
  14. * 1.0.1 通过openssl,RSA验证发送方具有刷数据的权限. -gwang 2017
  15. * 1.0.0 基础功能, 没有安全功能. -gwang 2017
  16. * @author gwang email:wanggangzero@qq.com
  17. * @copyright © 2015-12-1, SJZ LoyalSoft Corporation & gwang. All rights reserved.
  18. */
  19. /**
  20. * Description of kvflush
  21. * 写一个key=>value对到目标CMEM
  22. * @author gwang
  23. */
  24. class kvflush {
  25. /**
  26. * RSA 密钥路径
  27. */
  28. const keyPath = ROOTDIR . "/util/key";
  29. /**
  30. * 刷入数据
  31. */
  32. public static function flush() {
  33. InitZoneId(); # 初始化分区信息 Ps. $_REQUEST["zoneid"]
  34. $params = HttpUtil::getQueryParas();
  35. $key = CommUtil::zb64decode(urldecode($params["key"]));
  36. $val = CommUtil::zb64decode(urldecode($params["val"]));
  37. $user = urldecode($params["user"]);
  38. $type = urldecode($params['type']);
  39. $sign = urldecode($params['sign']);
  40. $myrsa = new MyRsa(self::keyPath);
  41. if (!$myrsa->verify_arr($params, $sign)) { # 验证下签名
  42. exit("签名验证失败!");
  43. }
  44. unset($myrsa);
  45. switch ($type) {
  46. case 'hash':
  47. $val = json_decode($val); # 需要还原为Obj才能解开
  48. $ret = self::FlushToMem_hmSet($key, $val);
  49. self::FlushToFile_hash($key, $val);
  50. break;
  51. case 'normal':
  52. $ret = self::FlushToMem_set($key, $val);
  53. self::FlushToFile_str($key, $val);
  54. break;
  55. default :
  56. $ret = self::FlushToMem_set($key, $val);
  57. self::FlushToFile_str($key, $val);
  58. break;
  59. }
  60. echo($ret ? "success" : "[$key] flush to mem failed!");
  61. self::log($user, $key); # 记录日志
  62. }
  63. static function log($user, $modelname) {
  64. $who = $user . '_' . HttpUtil::clientIP();
  65. $key = "log-flush";
  66. CLog::warn($who . "flushing [$modelname]", __CLASS__); # 写文件
  67. $ret = gMem()->hset($key, $who, TimeUtil::tsYmdHis()); # 写入mem
  68. return $ret;
  69. }
  70. /**
  71. * 普通写入方法
  72. * @param string $key
  73. * @param mixed $value
  74. * @return boolean
  75. */
  76. public static function FlushToMem_set($key, $value) {
  77. $mem = gMem();
  78. $mem->delete($key);
  79. $ret = $mem->set($key, $value); # 写入mem
  80. return $ret;
  81. }
  82. /**
  83. * 写入哈希表
  84. * @param string $key
  85. * @param obj/assoc_arr $assoc_array
  86. * @return type
  87. */
  88. public static function FlushToMem_hmSet($key, $assoc_array) {
  89. if (!is_array($assoc_array)) {
  90. if (is_object($assoc_array)) {
  91. $assoc_arr = array();
  92. foreach ($assoc_array as $k => $v) { # 组合成符合hmset的关联数组
  93. $assoc_arr[$k] = JsonUtil::encode($v);
  94. }
  95. $assoc_array = $assoc_arr;
  96. } else {
  97. return false;
  98. }
  99. }
  100. $ret = TRUE;
  101. $mem = gMem();
  102. if (count($assoc_arr) > 0) {
  103. $mem->delete($key);
  104. $ret = $mem->hmset($key, $assoc_array); # 写入
  105. }
  106. return $ret;
  107. }
  108. // <editor-fold defaultstate="collapsed" desc=" 私有方法 ">
  109. /**
  110. * 获取输出路径
  111. * @return type
  112. */
  113. private static function getFolder() {
  114. if (defined('CodeGen_Folder')) {
  115. if (!dir(CodeGen_Folder)) {
  116. if (mkdir(CodeGen_Folder)) {
  117. return CodeGen_Folder;
  118. }
  119. } else {
  120. return CodeGen_Folder;
  121. }
  122. }
  123. return ROOTDIR . '/configs/data/';
  124. }
  125. /**
  126. * 输出到文件
  127. * @param type $key
  128. * @param type $value
  129. */
  130. private static function writePHPFile($key, $value) {
  131. if (defined('CodeGen_Enabled') && CodeGen_Enabled) { # (部署环境)是否允许代码生成
  132. $file = fopen(self::getFolder() . $key . ".php", 'w');
  133. $str = "<?php " . PHP_EOL . " return unserialize(gzinflate(base64_decode('" . base64_encode(gzdeflate(serialize($value), 9)) . "')));";
  134. fwrite($file, $str);
  135. fclose($file);
  136. }
  137. }
  138. /**
  139. * 向文件中输出一个字符串
  140. * @param type $key
  141. * @param type $value
  142. */
  143. private static function FlushToFile_str($key, $value) {
  144. if ($key == "gamecfg-client") {
  145. self::writePHPFile($key, $value);
  146. } else {
  147. self::writePHPFile($key, JsonUtil::decode($value));
  148. }
  149. }
  150. /**
  151. * 向文件中输入一个hash对象
  152. * @param type $key
  153. * @param type $assoc_array
  154. */
  155. private static function FlushToFile_hash($key, $assoc_array) {
  156. self::writePHPFile($key, $assoc_array);
  157. }
  158. // </editor-fold>
  159. }
  160. HttpUtil::PostOnly();
  161. kvflush::flush(); # do it