小五博客 //www.lcvmw.cn 编程开发,大数据研究学习,搜索营销,SEO,搜索引擎优化 Mon, 18 Dec 2017 02:50:11 +0000 zh-CN hourly 1 Java跨域经验一则 //www.lcvmw.cn/yunwei/nginx/4172.html //www.lcvmw.cn/yunwei/nginx/4172.html#respond Mon, 18 Dec 2017 02:50:11 +0000 //www.lcvmw.cn/?p=4172 ?

最近开发了一个Java的后端小程序,在微信小程序这边使用Web-view进行HTML5的嵌套,然后用Ajax进行接口的调用。后端的接口使用Java的格式进行返回。

?

然后,使用postman进行请求能正常返回,使用HTML却无法得到结果。料想应该是浏览器的跨域问题。

?

然后添加一段SpringBoot的代码解决全局所有域名的跨域调用。

?

代码如下:

/**
* CORS全局统一跨域设置,所有均可跨域
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}

@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}

?

这段代码过于粗暴,无法控制跨域的请求域名,还可以通过CrosFilter的形式进行自定义设置,还在研究中。

?

顺手找了一段HTML用于测试跨域问题是否存在。存档备用。cros_test.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域测试</title>
<script src="//apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
function crosRequest() {
$.ajax({
url: '//112.111.1.1:8092/api/v1/getHotList',
type: 'post',
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
source: 'baidu',
category: 'index'
}),
success: function (data) {
console.log(data);
}
});
}
</script>
</head>
<body>
<button onclick="crosRequest()">请求跨域资源</button>
</body>
</html>

?

核心点在于加上JSON.stringify,才能以POST JSON的形式提交Java后端。

然后在Console里面可以看到是否是跨域的问题造成的无法请求。

?

另:在测试跨域的时候,cros_test.html不要放到接口同域下面,否则测试不了,可以本地使用hosts建一个虚拟空间,配合Nginx把cros_test.html放到a.com下面,然后接口访问b.com的接口,才能测试出是否有跨域的问题。

?

?

?

?

?

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《Java跨域经验一则

]]>
//www.lcvmw.cn/yunwei/nginx/4172.html/feed 0
测试新的WordPress编辑工具 //www.lcvmw.cn/daily/4171.html //www.lcvmw.cn/daily/4171.html#respond Thu, 07 Dec 2017 10:41:54 +0000 //www.lcvmw.cn/?p=4171 ?

新换了一个编辑工具MarsEdit,测试一下效果怎么样,太久没更新了,要准备开始更新内容了。

?

?

测试。。。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《测试新的WordPress编辑工具

]]>
//www.lcvmw.cn/daily/4171.html/feed 0
Shell自动备份Gitlab仓库的数据 //www.lcvmw.cn/yunwei/4170.html //www.lcvmw.cn/yunwei/4170.html#respond Wed, 02 Aug 2017 08:02:47 +0000 //www.lcvmw.cn/?p=4170  

很久没有更新了,抽时间快速整理一小段代码。

 

公司的Gitlab我在管理,一直没有时间做自动备份,生怕哪天出问题就完蛋了。

 

Gitlab自带有备份的功能,使用:

gitlab-rake gitlab:backup:create

即可在目录

/var/opt/gitlab/backups/下面生成备份的文件。

 

现在快速弄一个简单的Shell,做每天的自动备份以及历史备份的清理。

 

#!/bin/bash
#
# add to crontab :0 5 * * sh /data/scripts/backup_gitlab.sh
#

echo 'begin backup gitlab'

/opt/gitlab/bin/gitlab-rake gitlab:backup:create

echo 'Backp down! Begin copy to new folder'

# copy file created inner 60 minutes to backup folder
find "/var/opt/gitlab/backups/" -name "*.tar" -cmin -60 -type f -exec cp -R {} /data/backup/ \;

# delete old 2 day file
find "/var/opt/gitlab/backups/" -name "*.tar" -ctime +2 -type f -exec rm -rf {} \;

# delete 7 day files
find "/data/backup/" -name "*.tar" -ctime +7 -type f -exec rm -rf {} \;

echo 'backup gitlab work done'

主要用到的几个Find命令。

第一个-cmin –60 指60分钟以内创建的文件进行搜索

-ctime +2 指2天以前创建的文件

同理+7 代表7天以前创建的文件。

 

最后的逻辑是这样的:

1、备份

2、复制到/data/backup/目录统一管理

3、清理git自身目录2天以前的备份文件

4、清理backup目录7天以前的文件,因为我是每天备份,相当于保留7天数据。

 

然后chmod +x backup_git.sh 设置脚本具有执行权限。

放到目录/data/scripts下面。

 

使用crontab -e编辑定时任务

末尾加上:

0 5 * * * sh /data/scripts/backup_gitlab.sh

 

保存之后/etc/init.d/crond restart重启定时任务。

 

好了。以后每天凌晨5点会自动进行备份,并清理数据,如果有需要传到远程,再加上代码就Over了。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《Shell自动备份Gitlab仓库的数据

]]>
//www.lcvmw.cn/yunwei/4170.html/feed 0
记一次LNMP 1.4环境运行Lavavel5.2发布Nginx空白页面异常 //www.lcvmw.cn/sitebuild/laravel/4168.html //www.lcvmw.cn/sitebuild/laravel/4168.html#respond Sun, 11 Jun 2017 14:25:09 +0000 //www.lcvmw.cn/?p=4168  

本地运行的Larave一切正常,LNMP发布了最新的1.4版,以往一直使用这个做为Web环境,于是立即在服务器重新布署安装用上了。

 

自带的phpmyadmin什么的一切正常。传上Laravel之后,打开页面,确是空白的。

 

Nginx没有捕捉到错误信息,Laravel也没有任何错误日志记录,这就非常奇怪了。

 

于在在laravel目录/public/index.php这个入口文件的最开头加上echo ‘test1’;,结尾最后一行加上echo ‘test2’;

 

发现test1执行了,test2没执行,想能可能是Laravel没启动。

 

于是想再打开更明细的日志,看问题可能是什么地方,打开Nginx.conf配置,把开头的

error_log  /home/wwwlogs/nginx_error.log  crit;

 

改为info。这样会记录下绝大多数错误信息。

 

重启nginx之后,在日志里面终于找到了错误原因:

*31 FastCGI sent in stderr: "PHP message: PHP Warning:  require(): open_basedir restriction in effect. File(/data/test.cn/path.php) is not within the allowed path(s): (/data/test.cn/public/:/tmp/:/proc/) in /data/car3.cn/public/index.php on line 10

 

原来是php设置了路径限制,以确保程序安全。我用的这个laravel是经过自己改装的,会引用公共的系统文件,不知道原生的是否也会有这个问题。

 

打开Nginx的虚拟主机配置文件,在/usr/local/nginx/conf/vhost/域名.conf下面。

 

看到只有一个enable-php.conf,再打开enable-php.conf,再发现一个fastcgi.conf的引用。

在最后终于找到的配置所在:

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";

 

由于安全性的考虑,在安装的时候会自动打开这处安装限制,禁止程序跨目录引用另外的文件。

 

在一些框架里面,常常有跨目录引用。才会造成这处错误。

 

于是注释 第二行带openbasedir的。重启整个lnmp ,lnmp restart。

 

再访问页面,一切正常。。。

 

 

然后把nginx的错误日志还原为crit,否则info的方式,会记录非常非常多的垃圾日志出来。

 

LNMP是个非常非常好用的web环境,下载回本地之后,还可以增加多处自定义配置, 但是日常使用的时候,也不一定能满足定制化的需求 。

 

一定要学会发现问题,才能最好的解决问题。多思考问题和出路。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《记一次LNMP 1.4环境运行Lavavel5.2发布Nginx空白页面异常

]]>
//www.lcvmw.cn/sitebuild/laravel/4168.html/feed 0
Python多线程写文件的2种方案 //www.lcvmw.cn/coding/4166.html //www.lcvmw.cn/coding/4166.html#respond Wed, 10 May 2017 09:30:46 +0000 //www.lcvmw.cn/?p=4166 最近帮同事写一个批量查询数据的脚本。

从一个几十万行的文件内,读取第一行,查每一行是否收录。

单线程下面,效率非常低。

检查发现主要在请求网络时非常 慢。采用多线程之后,写文件到日志 里面成了最大的问题。

 

搜索了一下发现python并没有比较合适的并发写文件的示例。

 

参考了一些资料 ,总结出如下2种写法:

 

1、使用python的logging库。

自定义配置。需要做2步设置

首先使用cloghandler.ConcurrentRotatingFileHandler做为文件写出工具。需要sudo pip install ConcurrentLogHandler先安装再使用。。

然后把日志输出的格式改为format=%(message)s

除了信息不要任何东西。

 

然后并发时,使用

logging.config.fileConfig('logging.conf')
logger = logging.getLogger(__name__)

线程内使用:

logger.info(line.strip() + "," + htmlResult)

即可并发输出,效率有明显提升。

 

2、使用resultqueue = Queue.Queue()

多线程里面,取出每行URL,不停的请求页面,获取结果,把结果往resultqueue里面不停的写内容。

 

另开一个子线程读取resultqueue里面的内容,单线程循环写到文件内。单线程写文件速度还是非???,避免了多线程同时操作文件的问题。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 把queue队列里面的内容循环取出来写到文件,单个线程去操作
class WriteFileThread(threading.Thread):
?   def __init__(self, queue):
?       threading.Thread.__init__(self)
?       self.queue = queue

?   def run(self):

?       output = codecs.open('result.txt', 'w')

?       emptyCount = 0
?       while True:

?           if emptyCount > 20:
?               print '连续20次没有数据可获取,自动结束队列了'
?               break

?           # 如果队列为空,标记为空
?           if (self.queue.empty()):
?               emptyCount += 1  # 为空次数加1
?               print "队列为空,第%s次休息,2秒再检查" % emptyCount
?               time.sleep(2)  # 休息2秒

?           else:
?               emptyCount = 0  # 只要队列不是空的,就重置这个等待次数,以防断断续续导致提前退出
?               result = self.queue.get()

?               print '从队列获取到结果:' + result
?               output.write(result + "\r\n")  # 从队列里面读取出来的结果直接写到文件里面

?               # self.queue.task_done()

?       self.queue.task_done()
?       print "结束任务,写入文件关闭 At 【%s】" % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
?       output.close()

刚用python,代码粗漏。

3、把queue换成redis,更好用。

 

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《Python多线程写文件的2种方案

]]>
//www.lcvmw.cn/coding/4166.html/feed 0
Java使用Jedis操作Redis并发时遇到的坑记录 //www.lcvmw.cn/coding/java/4163.html //www.lcvmw.cn/coding/java/4163.html#respond Wed, 12 Apr 2017 10:23:33 +0000 //www.lcvmw.cn/?p=4163  

Java在使用jedis操作redis数据时,遇到坑,各种查资料解决了将近1天才实现结果。

 

坑1:

直接在Idea里面,建TestNG的Test类时,

里面的多线程代码,一直会提示报错,没有任何提示,直接就test任务结束。

解决方案:使用main建入口的方式进行测试,千万不要使用testng的@Test注解这种方式进行测试。

 

原因,估计是多线程引起的。怎么弄还不明白,只能换成main方法里面去执行多线程。

 

坑2:

多线程并发会造成冲突,会报各种错。

 

解决方法:使用JRedisPool建立线程池。

 

而且在操作时,使用synchronized把操作方法进行封装。否则依然会报错。

 

坑3:

超出线程池容量。1000个线程,会报大量的错。

 

解决方法:

JedisPoolConfig里面设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
setMaxTotal为1000,即可以连接的最大数量。


然后并发1000个线程都可以操作Redis了。完美。

大概的代码:

public class JedisUtils {

?   protected static Logger logger = LoggerFactory.getLogger(JedisUtils.class);

?   //Redis服务器IP
?   private static String ADDR_ARRAY = "127.0.0.1";

?   //Redis的端口号
?   private static int PORT = 6379;

?   //访问密码
?   private static String AUTH = "";

?   //可用连接实例的最大数目,默认值为8;
?   //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
?   private static int MAX_ACTIVE = 500;

?   //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
?   private static int MAX_IDLE = 100;

?   //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
?   private static int MAX_WAIT = 10 * 1000;

?   private static int TIMEOUT = 10 * 1000;//超时时间

?   //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
?   private static boolean TEST_ON_BORROW = true;

?   private static JedisPool jedisPool = null;

?   /**
?    * 初始化Redis连接池
?    */
?   private static void initialPool() {
?       try {
?           JedisPoolConfig config = new JedisPoolConfig();
?           config.setMaxTotal(MAX_ACTIVE);
?           config.setMaxIdle(MAX_IDLE);
?           config.setMaxWaitMillis(MAX_WAIT);

?           config.setTestOnBorrow(TEST_ON_BORROW);//使用时进行扫描,确保都可用

?           config.setTestWhileIdle(true);//Idle时进行连接扫描

?           config.setTestOnReturn(true);//还回线程池时进行扫描
//
////表示idle object evitor两次扫描之间要sleep的毫秒数
//            config.setTimeBetweenEvictionRunsMillis(30000);
//
////表示idle object evitor每次扫描的最多的对象数
//            config.setNumTestsPerEvictionRun(10);
//
////表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
//            config.setMinEvictableIdleTimeMillis(60000);

?           if (StringUtils.isNotBlank(AUTH)) {
?               jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);
?           } else {
?               jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT);
?           }

?       } catch (Exception e) {
?           logger.error("First create JedisPool error : " + e);
?           try {
?               //如果第一个IP异常,则访问第二个IP
?               JedisPoolConfig config = new JedisPoolConfig();
?               config.setMaxTotal(MAX_ACTIVE);
?               config.setMaxIdle(MAX_IDLE);
?               config.setMaxWaitMillis(MAX_WAIT);
?               config.setTestOnBorrow(TEST_ON_BORROW);
?               jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[1], PORT, TIMEOUT, AUTH);
?           } catch (Exception e2) {
?               logger.error("Second create JedisPool error : " + e2);
?           }
?       }
?   }

?   /**
?    * 在多线程环境同步初始化
?    */
?   private static synchronized void poolInit() {
?       if (jedisPool == null) {
?           initialPool();
?       }
?   }


?   /**
?    * 同步获取Jedis实例
?    *
?    * @return Jedis
?    */
?   public synchronized static Jedis getJedis() {
?       if (jedisPool == null) {
?           poolInit();
?       }

?       Jedis jedis = null;
?       try {
?           if (jedisPool != null) {
?               jedis = jedisPool.getResource();
?           }
?       } catch (Exception e) {
?           logger.error("Get jedis Error : " + e.getMessage(), e);
?       } finally {
?           returnResource(jedis);//归还到Redis池里面
?       }
?       return jedis;
?   }

?   /**
?    * 释放jedis资源
?    *
?    * @param jedis
?    */
?   public static void returnResource(final Jedis jedis) {
?       if (jedis != null && jedisPool != null) {
?           jedisPool.returnResource(jedis);
?       }
?   }

?   /**
?    * 关闭连接池
?    */
?   public static void closePool() {
?       if (jedisPool != null) {
?           jedisPool.close();
?       }
?   }

?   /**
?    * 设置 String
?    *
?    * @param key
?    * @param value
?    */
?   public synchronized static void setString(String key, String value) {
?       try {
?           value = StringUtils.isEmpty(value) ? "" : value;
?           getJedis().set(key, value);
?       } catch (Exception e) {
?           logger.error("Set key error : " + e);
?       }
?   }

?   /**
?    * 设置 过期时间
?    *
?    * @param key
?    * @param seconds 以秒为单位
?    * @param value
?    */
?   public synchronized static void setString(String key, int seconds, String value) {
?       try {
?           value = StringUtils.isEmpty(value) ? "" : value;
?           getJedis().setex(key, seconds, value);
?       } catch (Exception e) {
?           logger.error("Set keyex error : " + e);
?       }
?   }

?   /**
?    * 获取String值
?    *
?    * @param key
?    * @return value
?    */
?   public synchronized static String getString(String key) {
?       if (getJedis() == null || !getJedis().exists(key)) {
?           return null;
?       }
?       return getJedis().get(key);
?   }

}

 

 

 

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《Java使用Jedis操作Redis并发时遇到的坑记录

]]>
//www.lcvmw.cn/coding/java/4163.html/feed 0
php Laravel5.2框架遇到的小问题 //www.lcvmw.cn/coding/php/4161.html //www.lcvmw.cn/coding/php/4161.html#respond Wed, 15 Feb 2017 07:11:59 +0000 //www.lcvmw.cn/?p=4161  

Laravel是我的神器之一,最近升级到5.2,又是新增了非常多的特性。

 

写代码的遇到习惯性的写了一个有问题的代码出来

 

Larave使用Model查询一般有2种大概的查询写法:

Collect::find($collectId);根据ID直接查

另一种是Collect::where(‘id’,$collectId)->first();

 

写的时候不小心写成了Collect::find($collectId)->first();

 

这个写法是错误的,但是并没有报异常,日志也没有记录。后来不注意才发现这个错误写法。

 

但是返回的并不是这个ID的结果,直接查出来数据库的第一条结果。这种写法本身应该是有冲突的。

 

但是Laravel的链式操作并没有弄清楚,也没报错。

 

一般遇到解决不了的问题,我会打开Laravel的监听器,监听SQL查询语句,以便定位问题所在。以后有机会再分享。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《php Laravel5.2框架遇到的小问题

]]>
//www.lcvmw.cn/coding/php/4161.html/feed 0
C# 使用NCrawler爬虫全站采集 //www.lcvmw.cn/coding/csharp/4140.html //www.lcvmw.cn/coding/csharp/4140.html#respond Mon, 13 Feb 2017 03:49:47 +0000 //www.lcvmw.cn/?p=4140  

公司业务需要,需要采集一个表情站的所有内容,由于目标站下属二级分类太多。所以不想去直接按分类写规则。

 

虽然火车也可以实现但是得填充非常多的列表页进去,于是自己用C#来实现全站爬虫,再从中过滤不需要的文章规则。

 

在Nuget下载了NCrawler的库,这个C#的库比较老,已经相当长的时间没有再更新了。但是能用就成,不用非得去纠结最佳实现,

 

快速迭代的业务,优先以实现为主。下载回来发现引用了HtmlAgilityPack。但是是1.4.9版,和我另一个库有冲突,另一个库用的最新的1.4.9.5版。

 

于是下载源码重新编译。

 

最原始的库在

https://ncrawler.codeplex.com 然后github里面有人存了一份,从https://github.com/kant2002/NCrawler 下载,还发现一份官方的升级版在

https://github.com/esbencarlsen/NCrawler,被搞懵圈了,发现代码并不一致,于是下载了dant2002回来编译,

 

引用了新的HtmlAgilityPack之后成功编译,但是运行时会报错。找了大半天也没找到原因在哪里,我只需要引用新的HtmlAgilityPack,所以

 

把Nuget上可用的Dll导出来,用Refector对比源码,发现需要修改2处才可以使用。

 

打开NCrawlerModule.cs文件

改为下面这个,注释掉ThreadTaskRunnerService这行

//#if !DOTNET4 && !PORTABLE
//            builder.Register(c => new ThreadTaskRunnerService()).As<ITaskRunner>().InstancePerDependency();
//#else
            builder.Register(c => new NativeTaskRunnerService()).As<ITaskRunner>().InstancePerDependency();
//#endif

 

再找到Utils\MemoryStreamWithFileBackingStore.cs

        public override void Close()
        {
            if (m_MemoryStream != null)
            {
                m_Data = m_MemoryStream.ToArray();
                m_MemoryStream.Dispose();
                m_MemoryStream = null;
            }

            if (m_FileStoreStream != null)
            {
                m_FileStoreStream.Dispose();
                m_FileStoreStream = null;
            }

            //base.Close();
        }

把最后一个行的base.Clonse()注释掉,此行会触发异常。

 

然后以.net 4.5编译。成功出DLL。引用至项目,开始使用。

 

封装一个自己的类

1

 

使用时通过Xpath(HtmlAgility快速通过XPath取值)快速取出所需数据。封入界面,即可使用。

 

发现Xpath比正则更好使。

 

最后效果如下:

2

 

 

还有谁有推荐的C#爬虫,求推荐,这个源码太老,只能勉强使用,感觉速度也是一般般。

 

PS:

1、此采集会掉一些数,全站抓会费更多的时间,我不着急,慢慢采就O了。

2、可以再封装,实现任何网站的全站采集。只需要把过滤规则提取一遍,以后采集任何网站,都会比较Easy。

3、后续处理:以前是通过C#再写一遍入库的代码存Mysql。现在使用ETL工具Kettle,可以快速把Excel放进MySQL,也可以直接用Navicat导Excel进Mysql。

简单的事高效处理,不用再纠结怎么入库这种简单的活。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《C# 使用NCrawler爬虫全站采集

]]>
//www.lcvmw.cn/coding/csharp/4140.html/feed 0
PHP实现多线程并发操作数据库 //www.lcvmw.cn/coding/php/4135.html //www.lcvmw.cn/coding/php/4135.html#respond Wed, 28 Dec 2016 02:36:59 +0000 //www.lcvmw.cn/?p=4135 PHP用pcntl可以实现多线程操作数据库。直接上代码,逻辑自己研究喽。

 

示例代码为:

/**
 * 并发多线程运行任务,把任务拆解成区块,用多线程去并发执行
 * @param callable $exeWorkers [任务函数体]
 * @param [type]   $maxJob     [最大数量]
 * @param [type]   $threadNum    [线程数量]
 */
function runJobWithThread(callable $exeWorkers,$maxJob,$threadNum)
{
    $pids = array();

    for($i = 0; $i < $threadNum; $i++){

        $pids[$i] = pcntl_fork();

        switch ($pids[$i]) {
            case -1:
                echo "fork error : {$i} \r\n";
                exit;

            case 0:
                $totalPage=ceil($maxJob / $threadNum);
                $param = array(
                    //'lastid' => $maxJob / $threadNum * $i,
                    //'maxid' => $maxJob / $threadNum * ($i+1),

                    'page_start' => $totalPage*$i,
                    'page_end' => $totalPage*($i+1),
                );

                $exeWorkers($param);
                exit;

            default:
                break;
        }

    }

    foreach ($pids as $i => $pid) {
        if($pid) {
            pcntl_waitpid($pid, $status);
        }
    }
}

 

使用时:

//1000个任务,10个线程
runJobWithThread(function($para){
    echo '进程ID:'.getmypid().',最小ID是【'.$para['page_start'].'】最大ID为:【'.$para['page_end'].'】'.PHP_EOL;
},1011,10);

 

可以实现多线程操作数据。

 

并发链接数据库时,可以通过设置线程ID实现并发链接。

具体代码类似:

class DB {

    public static function getInstance()
    {
        static $instances = array();
        $key = getmypid();
        if (empty($instances[$key]))
        {
            $instances[$key] = new DB();
            
        }
        return $instances[$key];
    }
}

 

只放代码,具体可以自己尝试一下,并发操作数据库可以极大的提高处理数据的性能,在定时任务和数据处理的时候非常有用。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《PHP实现多线程并发操作数据库

]]>
//www.lcvmw.cn/coding/php/4135.html/feed 0
Mac下Navicat日志超标 //www.lcvmw.cn/yunwei/database/4130.html //www.lcvmw.cn/yunwei/database/4130.html#comments Tue, 20 Dec 2016 09:43:04 +0000 //www.lcvmw.cn/?p=4130 平时一直在用Navicat Premium破解的版本做各种关系数据库的链接。

 

今天查询过后,忘了一个SQL,又不想重写,准备找回来,Navicat会保存每次查询时使用的SQL语句到本地文件里面。

 

最后在/Users/user/Library/Application Support/PremiumSoft CyberTech/Navicat Premium 下面找到一个QueryExec.log日志文件,

 

竟然大于2GB。果断找到需要的SQL之后,删除此文件。

 

1

 

 

重写指定了自己指定的目录,方便寻找,也可以关闭查询的SQL日志,但是万一想用的时候,又会比较麻烦,写个脚本去清理又太麻烦了。

 

暂时先存在这个目录,以便以后使用吧。

声明: 本文采用 BY-NC-SA 协议进行授权 | 盛世北京赛车pk10历史记录
转载请注明转自《Mac下Navicat日志超标

]]>
//www.lcvmw.cn/yunwei/database/4130.html/feed 1
北京pk10计划软件 |