作者 邓超

x

@@ -17,112 +17,46 @@ function start(){ @@ -17,112 +17,46 @@ function start(){
17 // 进程管理器 17 // 进程管理器
18 $pm = new Process\Manager(); 18 $pm = new Process\Manager();
19 19
20 - // 启动一个进程来管理定时  
21 - $pm->add(function (Process\Pool $pool, int $workerId){  
22 - _echo("定时进程({$workerId})启动成功");  
23 -  
24 - // 每秒执行  
25 - \Swoole\Timer::tick(1000,function() use(&$pool){  
26 -  
27 - if(redis()->getOriginData('email_sync_stop_num') >= WORKER_NUM+1 ){  
28 - $pool->shutdown();  
29 - }  
30 -  
31 -  
32 -  
33 - //  
34 - \Lib\Log::getInstance()->write();  
35 -  
36 - });  
37 -  
38 -  
39 - // 进行阻塞,否则定时器无法运行  
40 - while (true){  
41 - co::sleep(10);  
42 - }  
43 -  
44 - },true);  
45 -  
46 -  
47 -// 协程配置  
48 - \co::set([  
49 - 'max_coroutine'=>COROUTINE_MAX_NUM, // 最大携程数量  
50 - 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置  
51 - ]);  
52 -  
53 // 启动业务进程 20 // 启动业务进程
54 $pm->addBatch(WORKER_NUM,function (Process\Pool $pool, int $worker_id){ 21 $pm->addBatch(WORKER_NUM,function (Process\Pool $pool, int $worker_id){
55 _echo("业务进程({$worker_id})启动成功"); 22 _echo("业务进程({$worker_id})启动成功");
56 23
57 - $start_num = 0;// 启动的协程数量  
58 -  
59 // 循环阻塞 24 // 循环阻塞
60 while (true){ 25 while (true){
61 -  
62 - if(redis()->get(SYNC_RUNNING_REDIS_KEY)=='stop'){  
63 - break;  
64 - }  
65 -  
66 - // 是否到了协程配置的数量上限  
67 - if($start_num < COROUTINE_MAX_NUM){ 26 + swoole_set_process_name('php-email-sync-list-'.$worker_id);
68 // 需要同步的id 27 // 需要同步的id
69 $id = redis()->lPop('sync_email_lists'); 28 $id = redis()->lPop('sync_email_lists');
70 29
71 if(!$id || !is_numeric($id)){ 30 if(!$id || !is_numeric($id)){
72 co::sleep(1); 31 co::sleep(1);
73 - }else{ 32 + }
  33 + else{
74 // 占用当前的id,占用2小时 34 // 占用当前的id,占用2小时
75 if(redis()->add('just_sync_'.$id,time(),600)){ 35 if(redis()->add('just_sync_'.$id,time(),600)){
76 // 启动一个协程 36 // 启动一个协程
77 - go(function () use (&$start_num,$worker_id,$id){  
78 - $start_num++; 37 + go(function () use ($id){
79 38
80 // 开始同步 39 // 开始同步
81 try { 40 try {
82 - sync($id,$worker_id); 41 + sync($id);
83 }catch (\Throwable $e){ 42 }catch (\Throwable $e){
84 - // 重新发布同步任务,如果失败了是否重新发布  
85 -// redis()->rPush('sync_email_lists',$id);  
86 -  
87 -// _echo($e->getMessage());  
88 logs( 43 logs(
89 $e->getMessage().PHP_EOL.$e->getTraceAsString(), 44 $e->getMessage().PHP_EOL.$e->getTraceAsString(),
90 - LOG_PATH.'/'.$worker_id.'.log' 45 + LOG_PATH.'/sync/'.$id.'.log'
91 ); 46 );
92 } 47 }
93 48
94 // 协程完成后执行的函数 49 // 协程完成后执行的函数
95 - co::defer(function () use (&$start_num,$worker_id,$id){  
96 -// _echo('正常关闭进程('.$worker_id.')下的协程('.co::getCid().')');  
97 - $start_num--; 50 + co::defer(function () use ($id){
98 // 消除占用 51 // 消除占用
99 redis()->delete('just_sync_'.$id); 52 redis()->delete('just_sync_'.$id);
100 // 写入日志 53 // 写入日志
101 \Lib\Log::getInstance()->write(); 54 \Lib\Log::getInstance()->write();
102 -  
103 }); 55 });
104 56
105 }); 57 });
106 } 58 }
107 } 59 }
108 - }else{  
109 - // 协程到了最大的数量,阻塞1秒  
110 - co::sleep(1);  
111 - }  
112 -  
113 -  
114 - }  
115 -  
116 - // 验证是否全部进程退出了  
117 - while (true){  
118 - if(!$start_num){  
119 - redis()->incr('email_sync_stop_num');  
120 - break;  
121 - }  
122 - co::sleep(0.5);  
123 - }  
124 - while (true){  
125 - co::sleep(99);  
126 } 60 }
127 61
128 },true); 62 },true);
@@ -130,16 +64,9 @@ function start(){ @@ -130,16 +64,9 @@ function start(){
130 // 启动一个同步内容的进程 64 // 启动一个同步内容的进程
131 $pm->add(function (Process\Pool $pool, int $worker_id){ 65 $pm->add(function (Process\Pool $pool, int $worker_id){
132 _echo("业务进程({$worker_id})启动成功,body"); 66 _echo("业务进程({$worker_id})启动成功,body");
133 -  
134 - $start_num = 0;// 启动的协程数量  
135 - 67 + swoole_set_process_name('php-email-sync-body-'.$worker_id);
136 // 循环阻塞 68 // 循环阻塞
137 while (true){ 69 while (true){
138 - if(redis()->get(SYNC_RUNNING_REDIS_KEY)=='stop'){  
139 - break;  
140 - }  
141 - // 是否到了协程配置的数量上限  
142 - if($start_num < 500){  
143 // 需要同步的id 70 // 需要同步的id
144 $id = redis()->lPop('sync_email_body'); 71 $id = redis()->lPop('sync_email_body');
145 72
@@ -149,56 +76,35 @@ function start(){ @@ -149,56 +76,35 @@ function start(){
149 // 占用当前的id,占用2小时 76 // 占用当前的id,占用2小时
150 if(redis()->add('just_sync_body_'.$id['lists_id'],time(),600)){ 77 if(redis()->add('just_sync_body_'.$id['lists_id'],time(),600)){
151 // 启动一个协程 78 // 启动一个协程
152 - go(function () use (&$start_num,$worker_id,$id){  
153 -  
154 - $start_num++; 79 + go(function () use ($id){
155 80
156 // 开始同步 81 // 开始同步
157 try { 82 try {
158 - sync_body($id,$worker_id); 83 + sync_body($id);
159 }catch (\Throwable $e){ 84 }catch (\Throwable $e){
160 // _echo($e->getMessage()); 85 // _echo($e->getMessage());
161 logs( 86 logs(
162 $e->getMessage().PHP_EOL.$e->getTraceAsString(), 87 $e->getMessage().PHP_EOL.$e->getTraceAsString(),
163 - LOG_PATH.'/'.$worker_id.'.log' 88 + LOG_PATH.'/'.$id['lists_id'].'.log'
164 ); 89 );
165 } 90 }
166 91
167 // 协程完成后执行的函数 92 // 协程完成后执行的函数
168 - co::defer(function () use (&$start_num,$worker_id,$id){ 93 + co::defer(function () use ($id){
169 // _echo('正常关闭进程('.$worker_id.')下的协程('.co::getCid().')'); 94 // _echo('正常关闭进程('.$worker_id.')下的协程('.co::getCid().')');
170 - $start_num--;  
171 // 消除占用 95 // 消除占用
172 redis()->delete('just_sync_body_'.$id['lists_id']); 96 redis()->delete('just_sync_body_'.$id['lists_id']);
173 // 写入日志 97 // 写入日志
174 \Lib\Log::getInstance()->write(); 98 \Lib\Log::getInstance()->write();
175 99
176 -  
177 }); 100 });
178 101
179 }); 102 });
180 } 103 }
181 } 104 }
182 - }else{  
183 - // 协程到了最大的数量,阻塞1秒  
184 - co::sleep(1);  
185 - }  
186 -  
187 105
188 } 106 }
189 107
190 - // 验证是否全部进程退出了  
191 - while (true){  
192 - if(!$start_num){  
193 - redis()->incr('email_sync_stop_num');  
194 - break;  
195 - }  
196 - co::sleep(0.5);  
197 - }  
198 - while (true){  
199 - co::sleep(99);  
200 - }  
201 -  
202 },true); 108 },true);
203 109
204 // 启动管理器 110 // 启动管理器
@@ -214,7 +120,7 @@ function start(){ @@ -214,7 +120,7 @@ function start(){
214 * @author:dc 120 * @author:dc
215 * @time 2023/3/23 10:18 121 * @time 2023/3/23 10:18
216 */ 122 */
217 -function sync_body($id,$worker_id){ 123 +function sync_body($id){
218 124
219 // 是否有数据 125 // 是否有数据
220 if(db()->count(\Model\bodySql::has((int) $id['lists_id']))){ 126 if(db()->count(\Model\bodySql::has((int) $id['lists_id']))){
@@ -256,7 +162,7 @@ function sync_body($id,$worker_id){ @@ -256,7 +162,7 @@ function sync_body($id,$worker_id){
256 * @author:dc 162 * @author:dc
257 * @time 2023/3/10 10:19 163 * @time 2023/3/10 10:19
258 */ 164 */
259 -function sync($email_id,$worker_id){ 165 +function sync($email_id){
260 166
261 $email = db()->first(\Model\emailSql::first($email_id)); 167 $email = db()->first(\Model\emailSql::first($email_id));
262 if(!$email){ 168 if(!$email){
@@ -277,8 +183,8 @@ function sync($email_id,$worker_id){ @@ -277,8 +183,8 @@ function sync($email_id,$worker_id){
277 // $mailServer->client->debug(true,LOG_PATH.'/'.$email_id.'/'); 183 // $mailServer->client->debug(true,LOG_PATH.'/'.$email_id.'/');
278 184
279 // 同步文件夹 185 // 同步文件夹
280 - $mailServer->syncFolder($email_id,db());  
281 - 186 + $mailServer->syncFolder($email_id);
  187 + _echo('文件夹同步成功-'.$email_id);
282 188
283 // 读取到邮箱中的文件夹 189 // 读取到邮箱中的文件夹
284 $folders = db()->all(\Model\folderSql::all($email['id'])); 190 $folders = db()->all(\Model\folderSql::all($email['id']));
@@ -289,10 +195,12 @@ function sync($email_id,$worker_id){ @@ -289,10 +195,12 @@ function sync($email_id,$worker_id){
289 foreach ($folders as $folder){ 195 foreach ($folders as $folder){
290 try { 196 try {
291 if(empty($folder['_child'])){ 197 if(empty($folder['_child'])){
  198 + _echo('同步文件夹('.$folder['origin_folder'].')邮件列表');
292 // 同步父文件夹 199 // 同步父文件夹
293 $mailServer->syncMail($email_id,$folder['id'],$folder['origin_folder']); 200 $mailServer->syncMail($email_id,$folder['id'],$folder['origin_folder']);
294 }else{ 201 }else{
295 foreach ($folder['_child'] as $item){ 202 foreach ($folder['_child'] as $item){
  203 + _echo('同步文件夹('.$item['origin_folder'].')邮件列表');
296 // 同步子文件夹 204 // 同步子文件夹
297 $mailServer->syncMail($email_id,$item['id'],$item['origin_folder']); 205 $mailServer->syncMail($email_id,$item['id'],$item['origin_folder']);
298 } 206 }
@@ -319,41 +227,7 @@ if(!function_exists("imap_8bit")){ @@ -319,41 +227,7 @@ if(!function_exists("imap_8bit")){
319 227
320 228
321 229
322 -$ps = "ps -ef | grep \"sync.php start\" | grep -v grep | wc -l";  
323 -  
324 -switch ($argv[1]??0){  
325 - case 'start':{  
326 -// $num = exec($ps);  
327 -// if($num){  
328 -// echo '正则运行,请勿重复运行';  
329 -// }else{  
330 - start();  
331 -// }  
332 - break;  
333 - }  
334 - case 'stop':{  
335 - \Co\run(function ($ps){  
336 - echo "正在退出程序...\n非必要请不要强制kill掉进程\n";  
337 -  
338 - redis()->set(SYNC_RUNNING_REDIS_KEY,'stop');  
339 -  
340 - while (true){  
341 -  
342 - $num = exec($ps);  
343 - if(!$num){  
344 - break;  
345 - }  
346 - co::sleep(0.2);  
347 - }  
348 - echo "已退出程序\n";  
349 - },$ps);  
350 -  
351 - break;  
352 - }  
353 - default:{  
354 - break;  
355 - }  
356 -} 230 +start();
357 231
358 232
359 233
1 -<?php  
2 -//  
3 -///**  
4 -// * TODO:: 这个文件是定时去拉取所有邮箱中的邮件  
5 -// * 暂时不用这个  
6 -// */  
7 -////error_reporting();  
8 -//  
9 -//use Swoole\Process;  
10 -//  
11 -//  
12 -//  
13 -//include_once __DIR__."/../vendor/autoload.php";  
14 -//  
15 -//  
16 -//function start(){  
17 -//  
18 -//// 删除停止运行的值  
19 -// redis()->delete(SYNC_RUNNING_REDIS_KEY);  
20 -//  
21 -// /** 创建一个表 **/  
22 -// $table = new Swoole\Table(128);// 128 行  
23 -// $table->column('val', Swoole\Table::TYPE_INT);  
24 -// $table->create();  
25 -//  
26 -// // 初始时,进行一次统计  
27 -// $table->set('etotal',['val'=> db()->count(\Model\emailSql::count())]);  
28 -//  
29 -// // 进程管理器  
30 -// $pm = new Process\Manager();  
31 -//  
32 -// // 启动一个进程来管理定时  
33 -// $pm->add(function (Process\Pool $pool, int $workerId)use (&$table){  
34 -// _echo("定时进程({$workerId})启动成功");  
35 -// // 每10分钟统计一次邮箱数量  
36 -// \Swoole\Timer::tick(600000,function () use (&$table){  
37 -// $table->set('etotal',['val'=> db()->count(\Model\emailSql::count())]);  
38 -// });  
39 -//  
40 -// // 每2秒执行一次  
41 -// \Swoole\Timer::tick(2000,function () use (&$table,&$pool){  
42 -// // 是否停止脚本  
43 -// $table->set('stop',['val'=> redis()->get(SYNC_RUNNING_REDIS_KEY) === 'stop' ? 1 : 0]);  
44 -//// _echo('定时器');  
45 -// // 检查是否结束了所有的协程同步代码  
46 -// if ($table->get('stop','val')) {  
47 -// $stop_num = 0;  
48 -// foreach (range(0, WORKER_NUM) as $i) {  
49 -// if ($table->exists('ps' . $i)) {  
50 -// $stop_num++;  
51 -// }  
52 -// }  
53 -// if($stop_num >= WORKER_NUM){  
54 -//// 退出进程  
55 -// $pool->shutdown();  
56 -// }  
57 -// }  
58 -//  
59 -// // 邮件总数  
60 -// $total = redis()->get('email_total',0);  
61 -// if($total > $table->get('etotal','val')){  
62 -// $table->set('etotal',['val'=> $total]);  
63 -// }  
64 -//  
65 -// });  
66 -//  
67 -//  
68 -// //todo:: 需要更新同步的邮件,每10分钟同步一次,这里是的时间是微妙  
69 -// \Swoole\Timer::tick(600000,function (){  
70 -//  
71 -// start_now_mail();  
72 -//  
73 -// });  
74 -//  
75 -//  
76 -//  
77 -// // 进行阻塞,否则定时器无法运行  
78 -// while (true){  
79 -// co::sleep(9999);  
80 -// }  
81 -// },true);  
82 -//  
83 -//  
84 -//// 协程配置  
85 -// \co::set([  
86 -// 'max_coroutine'=>COROUTINE_MAX_NUM, // 最大携程数量  
87 -// 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置  
88 -// ]);  
89 -//  
90 -// // 启动业务进程  
91 -// $pm->addBatch(WORKER_NUM,function (Process\Pool $pool, int $worker_id) use (&$table){  
92 -// _echo("业务进程({$worker_id})启动成功");  
93 -//  
94 -// // 协程id集  
95 -// $cid = [];  
96 -//  
97 -// $i = 0;  
98 -// $email_total = $table->get('etotal','val');//邮件总数量  
99 -// $isRunMaxCNum = 1; // 允许最大协程数量,如果为0则停止所有协程工作,相当于停止脚本  
100 -// // 是否退出进程  
101 -// while (true){  
102 -// $i++;  
103 -// // 每10秒 验证一次邮箱数量,好控制协程的数量  
104 -// if($i>=10){  
105 -// $email_total = $table->get('etotal','val');  
106 -// $i = 0;  
107 -// }  
108 -//  
109 -// if(!$email_total){  
110 -// break;  
111 -// }  
112 -//  
113 -// // 每个协程 分配 10个邮箱任务  
114 -// $cnum = ceil($email_total/(WORKER_NUM*10));  
115 -// // 当前协程的数量  
116 -// $nowCnum = count($cid);  
117 -// // 说明 需要新的协程了  
118 -// if($cnum > $nowCnum){  
119 -// // 开启所需要的协程数量  
120 -// foreach (range(0,$cnum-$nowCnum) as $v){  
121 -// // 启动一个协程  
122 -// create_coroutine($cid,$isRunMaxCNum,$worker_id);  
123 -// }  
124 -// }  
125 -// // 暂时没有实现 减少协程数量操作  
126 -//// else if ($cnum < $nowCnum){  
127 -//// // 说明 协程数量过多,小于了1个协程处理10个邮箱的,资源闲置情况  
128 -//// // 销毁多余协程  
129 -//// $isRunMaxCNum = $nowCnum - $cnum;  
130 -//// }  
131 -//  
132 -// // 每3秒检查一次是否要停止 协程  
133 -// if($i%3 === 0){  
134 -//// _echo('是否收到退出信号:'.$table->get('stop','val'));  
135 -// if ($table->get('stop','val')){  
136 -// // 停止  
137 -// $isRunMaxCNum = 0;  
138 -// }  
139 -// }  
140 -//  
141 -// // 这个是检查 cid的如果协程全部退出,则退出进程  
142 -// co::sleep(1);  
143 -// // 跳出无限循环了  
144 -// if(!$cid){  
145 -// _echo('正常关闭进程('.$worker_id.')');  
146 -// break;  
147 -// }  
148 -// }  
149 -//  
150 -// // 是否停止,这里进行阻塞  
151 -// if ($table->get('stop','val')){  
152 -// // 某个进程退出了  
153 -// $table->set('ps'.$worker_id,['val'=>1]);  
154 -// // 阻塞直到 主进程 kill掉所有子进程  
155 -// while (true){  
156 -// co::sleep(5);  
157 -// }  
158 -// }  
159 -//  
160 -//  
161 -// },true);  
162 -//  
163 -//  
164 -// // 启动管理器  
165 -// $pm->start();  
166 -//  
167 -//}  
168 -//  
169 -///**  
170 -// * 创建协程  
171 -// * @param array $cid  
172 -// * @param int $isRunMaxCNum  
173 -// * @param $worker_id  
174 -// * @author:dc  
175 -// * @time 2023/2/14 17:04  
176 -// */  
177 -//function create_coroutine(array &$cid,int &$isRunMaxCNum,$worker_id){  
178 -// go(function () use (&$cid,&$isRunMaxCNum,$worker_id){  
179 -// // 协程id  
180 -// $cid[co::getCid()] = co::getCid();  
181 -//  
182 -// // 同步操作  
183 -// while (true){  
184 -// // 是否退出协程  
185 -// if(!$isRunMaxCNum){  
186 -//// _echo('协程('.co::getCid().'): stop '.$isRunMaxCNum);  
187 -// break;  
188 -// }  
189 -//  
190 -// // 开始同步  
191 -// try {  
192 -// sync($worker_id);  
193 -// }catch (\Throwable $e){  
194 -// _echo($e->getMessage());  
195 -// logs(  
196 -// $e->getMessage().PHP_EOL.$e->getTraceAsString(),  
197 -// LOG_PATH.'/'.$worker_id.'_'.co::getCid().'.log'  
198 -// );  
199 -// }  
200 -//  
201 -// // 阻塞1秒  
202 -// co::sleep(1);  
203 -// }  
204 -//  
205 -// // 协程完成后执行的函数  
206 -// co::defer(function () use (&$cid,$worker_id){  
207 -// _echo('正常关闭进程('.$worker_id.')下的协程('.co::getCid().')');  
208 -// unset($cid[co::getCid()]);  
209 -// });  
210 -//  
211 -// });  
212 -//}  
213 -//  
214 -//  
215 -///**  
216 -// * 开始同步, 这里是主要的业务代码  
217 -// * @param int $worker_id 进程号  
218 -// * @return int  
219 -// * @author:dc  
220 -// * @time 2023/2/18 11:27  
221 -// */  
222 -//function sync($worker_id=0){  
223 -// // 需要同步的id  
224 -// $id = redis()->lPop('sync_email_lists');  
225 -//  
226 -// if(!$id){  
227 -// co::sleep(1);  
228 -// return -1;  
229 -// }  
230 -//  
231 -// _echo($worker_id.': 协程('.co::getCid().'):抢到 '.$id);  
232 -//  
233 -// $email = db()->first(\Model\emailSql::first($id));  
234 -// if(!$email){  
235 -// return 0;  
236 -// }  
237 -//  
238 -// if($email['pwd_error']){  
239 -// return 1;  
240 -// }  
241 -//  
242 -// $mailServer = new Lib\Mail\Mail($email['email'],base64_decode($email['password']),$email['imap']);  
243 -//  
244 -// // 登录服务器  
245 -// if(!$mailServer->login()){  
246 -// return 2;  
247 -// }  
248 -//  
249 -// // 文件夹间隔1天同步一次  
250 -// if(empty($email['last_sync_time']) || time() > $email['last_sync_time']+86400){  
251 -// // 同步文件夹  
252 -// $mailServer->syncFolder($id,db());  
253 -// }  
254 -//  
255 -// // 读取到邮箱中的文件夹  
256 -// $folders = db()->all(\Model\folderSql::all($email['id']));  
257 -// if(!$folders){  
258 -// return 3;  
259 -// }  
260 -// $folders = list_to_tree($folders);  
261 -// foreach ($folders as $folder){  
262 -// try {  
263 -// if(empty($folder['_child'])){  
264 -// // 同步父文件夹  
265 -// $mailServer->syncMail($id,$folder['id'],$folder['origin_folder']);  
266 -// }else{  
267 -// foreach ($folder as $item){  
268 -// // 同步子文件夹  
269 -// $mailServer->syncMail($id,$item['id'],$item['origin_folder']);  
270 -// }  
271 -// }  
272 -//  
273 -// }catch (Throwable $e){  
274 -// logs(  
275 -// $e->getMessage(),  
276 -// LOG_PATH.'/imap/'.$email['email'].'.error.log'  
277 -// );  
278 -// }  
279 -// }  
280 -//  
281 -//  
282 -// $email = null;  
283 -// $mailServer = null;  
284 -//  
285 -//}  
286 -//  
287 -//  
288 -//  
289 -//  
290 -//switch ($argv[1]){  
291 -// case 'start':{  
292 -// start();  
293 -// break;  
294 -// }  
295 -// case 'stop':{  
296 -// \Co\run(function (){  
297 -// echo "正在退出程序...\n非必要请不要强制kill掉进程\n";  
298 -// redis()->set(SYNC_RUNNING_REDIS_KEY,'stop');  
299 -// while (true){  
300 -// $num = exec("ps -ef | grep \"sync_email.php start\" | grep -v grep | wc -l");  
301 -// if(!$num){  
302 -// break;  
303 -// }  
304 -// co::sleep(0.5);  
305 -// }  
306 -// echo "已退出程序\n";  
307 -// });  
308 -// break;  
309 -// }  
310 -// default:{  
311 -// break;  
312 -// }  
313 -//}  
314 -//  
315 -//  
316 -//  
317 -//  
318 -//  
319 -//  
320 -//  
321 -//  
322 -//  
323 -//