ES实现站内搜索

#####需求:

  • 支持对用户名称的站内搜索
  • 用户分多个平台,在mysql跨表,需要搜索多个表
  • 百万用户记录
  • mysql模糊匹配太慢

#####解决:

  • 1.同步mysql数据到elasticsearch
  • 2.通过关键字到elasticsearch匹配,获取到数据(有mysql索引支持)
  • 3.在mysql检索,业务处理,返回客户端
  • 注意: mysql与elasticsearch数据同步(全量更新+触发更新)

#####参考:

扩展elasticsearch

####横向扩展添加新节点
配置:

1
2
3
4
5
6
7
cluster.name: my-application
node.name: es4.xxx.com
path.data: /es
path.logs: /es/logs
network.host: 172.16.0.24
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["172.16.0.25","172.16.0.26","172.16.0.24","172.16.0.57","172.16.0.58"]

错误:

1
2
3
ERROR:
nested: IllegalArgumentException[No custom metadata prototype registered for type [licenses], node like missing plugins];
Solution:

解决:

1
2
./bin/plugin install license
./bin/plugin install mobz/elasticsearch-head

####纵向扩展升级原有节点

######1.关闭自动分片

1
2
3
4
5
6
curl -XPUT http://172.16.0.27:9200/_cluster/settings -d'
{
"transient" : {
"cluster.routing.allocation.enable" : "none"
}
}'

######2.升级配置,重启节点

######3.开启自动分片

1
2
3
4
5
6
curl -XPUT http://172.16.0.27:9200/_cluster/settings -d'
{
"transient" : {
"cluster.routing.allocation.enable" : "all"
}
}'

#####参考
http://www.tuicool.com/articles/RF7RBza

504

08:45开始:

####room服务:

1.  发现server 504 (nginx)
2.  [1040] Too many connections (php-fpm)

####server:

1.  nginx访问日志504.
2.  (request: "POST /index.php") execution timed out (136.359234 sec), terminating

####处理:

1. 查看nginx 访问日志, 发现大量504
2. 验证laravel框架错误,php错误日志,没发现错误。
3. 在php-fpm日志中发现执行超时终止执行,可能php-fpm阻塞
4. 重启cgi, nginx 返回200, 几分钟后又504了 (业务脚本对应服务器监控发现连接数飙升)
5. 怀疑可能是mysql阻塞,上阿里云rds查看,半小时内连接数直线上升.可能是脚本不断重启造成。临时关闭本机cron脚本。不生效。
6. rds临时扩容解决。

####监控分析如下:
7:40 — 8:10 业务脚本没有安全退出,pm2不停新启。半小时内phantomjs进程数达到100+,
8:10 — 8:40 系统负载200+(机器双核)
8:10 — 8:40 tcp连接数没采集到(系统负载过高)
8:40-8:43 连接数增量350
DB server : 08:45 — 09:10 连接数持续增长

刚好接上开始故障现象。

###总结:
故障,可能是几小时之前触发的。
系统负载过高时,会出现监控数据不全。
服务之间共享资源使用需谨慎。

Laravel重启单个队列

队列处理器是 long-lived 进程,如果代码改变而队列处理器没有重启,新代码是不生效的。laravel建议使用

1
php artisan queue:restart

但是这个操作会关闭所有正在运行的队列处理器,不会重启。但是若有多个队列,有时可能只更新了单个队列处理的代码。那就只需要重启对应队列处理器就行。

队列处理流程如下:(vendor/laravel/framework/src/Illuminate/Queue/Worker.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function daemon($connectionName, $queue = null, $delay = 0, $memory = 128, $sleep = 3, $maxTries = 0)
{
$lastRestart = $this->getTimestampOfLastQueueRestart();
while (true) {
if ($this->daemonShouldRun()) {
$this->runNextJobForDaemon(
$connectionName, $queue, $delay, $sleep, $maxTries
);
} else {
$this->sleep($sleep);
}
if ($this->memoryExceeded($memory) || $this->queueShouldRestart($lastRestart)
|| $this->inStopQueueSet($queue) ) {
$this->stop();
}
}
}
// 临时让指定queue自动关闭,用于重启单个queue
protected function inStopQueueSet($queue) {
return Redis::Sismember("laravel:stop:queues",$queue);
}

重启操作如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function restart($queue) {
Redis::Sadd("laravel:stop:queues",$queue);
while(true) {
sleep(1);
$worker = $this->getWorkerNum($queue);
if ( $worker == 0) {
echo "active worker: $worker\n";
break;
} else {
echo "active worker: $worker\n";
}
}
Redis::Srem("laravel:stop:queues",$queue);
$configs = $this->getLocalConfig();
$worker = $configs[$queue];
echo "start queue: $queue\n";
$this->process($queue,$worker,false);
}

fastcgi_finish_request

fastcgi_finish_request:
冲刷(flush)所有响应的数据给客户端并结束请求。 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行,后续脚本还是占用cgi进程。
避免业务流程太多,响应客户端速度过慢。

1
2
3
4
5
6
7
header("Content-Type: application/json");
echo json_encode([
'errno' => 0,
'message' => 'success',
]);
fastcgi_finish_request();
$this->doSomething();