SQLSERVER查询超时问题

SQLSERVER查询超时问题

问题描述

公司有一个正常运行的winform小程序,具体功能是定时跑一个任务,任务内容是从第三方数据库中查询出数据,存入另一个库。已经正常运行了一个多月,最近发现,从三天前开始,一些任务一直报`”Timeout 时间已到。在操作完成之前超时时间已过或服务器未响应。” 。但实际上服务器的网络是能够正常连接上第三方数据库的,并且使用UI工具执行相同SQL是非常快的。

分析问题

导致查询超时的原因会有很多种,根据这个答案的描述:

This type of timeout can have three causes;

  1. There’s a deadlock somewhere
  2. The database’s statistics and/or query plan cache are incorrect
  3. The query is too complex and needs to be tuned

首先排除了第一条,因为在查询工具中同样的查询语句是可以查询出数据的,不存在死锁、事务等问题。
其次第二条所描述的统计信息问题,因为数据库有定时任务进行统计信息的维护,所以不存在这个问题。
最后只剩下分析sql语句问题了,在工具中运行SQL执行计划分析,是可以走索引快速查询出数据的。这里因为程序使用的是ADO.NET的参数化查询,所以可能会存在实际生成的sql语句和数据库工具中的不一致。

问题定位

WinForm程序使用SqlClient对SQL Server数据库进行访问,其中使用到了参数化查询功能,进一步分析参数化查询片段代码是否正确。

问题代码

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
string IP="";
string SYS ="";
string sSql = @"select * FROM Table_User WHERE loginIP=@IP AND loginSys=@SYS";
SqlParameter[] param = new SqlParameter[]
{
new SqlParameter("@IP",IP),
new SqlParameter("@SYS",SYS)
};

using (SqlConnection conn = new SqlConnection(GetConnectString(_Type)))
{
using (SqlCommand sqlCommand = new SqlCommand())
{
try
{
PrepareCommand(sqlCommand, conn, null, SQLString, cmdParms);
int result = sqlCommand.ExecuteNonQuery();
sqlCommand.Parameters.Clear();
return result;
}
catch (SqlException ex)
{
foreach (SqlParameter sqlParameter in cmdParms)
{
SQLString = SQLString.Replace(sqlParameter.ParameterName, (sqlParameter.Value == null) ? "" : sqlParameter.Value.ToString());
}

throw new Exception(ex.Message + " SQL:" + SQLString);
}
}
}

void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, string cmdText, SqlParameter[] cmdParms)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}

cmd.Connection = conn;
cmd.CommandText = cmdText;
if (trans != null)
{
cmd.Transaction = trans;
}

cmd.CommandType = CommandType.Text;
if (cmdParms == null)
{
return;
}

foreach (SqlParameter sqlParameter in cmdParms)
{
if ((sqlParameter.Direction == ParameterDirection.InputOutput || sqlParameter.Direction == ParameterDirection.Input) && sqlParameter.Value == null)
{
sqlParameter.Value = DBNull.Value;
}

cmd.Parameters.Add(sqlParameter);
}
}

问题原因

根据微软文档描述:SqlParameter.DbType 属性,默认值为 NVarChar
在第三方库中的表结构字段类型都为VarChar类型,而SqlCommand中,因为没有设置参数类型,导致使用默认的NVarChar类型的SqlParameter进行参数化查询。
字段类型不匹配导致Sql查询从索引扫描变成了全表扫描,直接导致查询缓慢的问题。

问题修复

  1. 使用SqlParameter(String, SqlDbType, Int32)替代SqlParameter(String, Object),添加正确的DbType和size
  2. 直接使用SqlServer的查询分析器的默认匹配类型特点,改造sql语句。【不推荐】

排查故障参考

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The statement has been terminated
参数化查询比拼接字符串慢的原因
原因:

经过查阅资料和自己的分析后,得知原来是字符类型的不匹配造成的。因为这个数据表是客户数据库中的,我只是提取数据,而我一般建数据表都使用NVarchar类型,而客户的这个表使用的是Char(32),在查询分析器中直接写字符串作为查询条件时,查询优化器认为条件中等号两边的字符类型是相同的,从而会选择聚集索引查询,而在ADO.NET中使用SqlParameter后,因为字段类型错误导致了Sql查询从索引扫描变成了表扫描… 所以为了避免在Sql查询中由于条件字段类型不匹配而导致表扫描,记得以后在创建SqlParameter时声明SqlDbType就解决问题了。

使用JMeter进行压力测试

使用JMeter进行压力测试

前言

Postman的Runner不支持并行调用,无法模拟出多用户并发的情况。所以使用JMeter进行压力测试和一些并发测试。

练习Demo

CASTest.jmx
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
183
184
185
186
187
188
189
190
191
192
193
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="CASTest" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="更新测试接口" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">70</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP请求" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="service" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">UpdateTotal</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">service</stringProp>
</elementProp>
<elementProp name="appid" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">1999042740418347</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">appid</stringProp>
</elementProp>
<elementProp name="data" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;hoscode&quot;:&quot;${hoscode}&quot;,&quot;st&quot;:&quot;${st}&quot;,&quot;ed&quot;:&quot;${ed}&quot;}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">data</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain"></stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/API/PlatDict/UpdateTotal</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV 数据文件设置" enabled="true">
<stringProp name="delimiter">,</stringProp>
<stringProp name="fileEncoding">UTF-8</stringProp>
<stringProp name="filename">../workspace/JMterTest.csv</stringProp>
<boolProp name="ignoreFirstLine">true</boolProp>
<boolProp name="quotedData">false</boolProp>
<boolProp name="recycle">true</boolProp>
<stringProp name="shareMode">shareMode.group</stringProp>
<boolProp name="stopThread">false</boolProp>
<stringProp name="variableNames">st,ed,hoscode</stringProp>
</CSVDataSet>
<hashTree/>
</hashTree>
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.port">7957</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path"></stringProp>
<stringProp name="HTTPSampler.concurrentPool">6</stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</ConfigTestElement>
<hashTree/>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP信息头管理器" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="Content-Type" elementType="Header">
<stringProp name="Header.name">Content-Type</stringProp>
<stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="响应断言" enabled="true">
<collectionProp name="Asserion.test_strings">
<stringProp name="49586">200</stringProp>
</collectionProp>
<stringProp name="Assertion.custom_message">test error</stringProp>
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
<boolProp name="Assertion.assume_success">false</boolProp>
<intProp name="Assertion.test_type">8</intProp>
</ResponseAssertion>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="查看结果树" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合报告" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
JMetertest.csv
1
2
st,ed,hoscode
2022-07-01,2022-08-31,QJ00101

无UI启动

run.bat
1
G: cd Soft\apache-jmeter-5.5\bin jmeter -n -t G:\Soft\apache-jmeter-5.5\WorkSpace\CASTest.jmx -l G:\Soft\apache-jmeter-5.5\WorkSpace\result\result.txt -e -o G:\Soft\apache-jmeter-5.5\WorkSpace\webreport

参考

服务端性能测试-工具篇
使用 JMeter 进行压力测试
文章截图:
使用 JMeter 进行压力测试

使用 JMeter 进行压力测试


截图2

截图2

vsocde便携版设置文件关联图标

参考文章:https://blog.csdn.net/weixin_44220976/article/details/116354243

vscode_icon.reg
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.json\OpenWithProgids]
"VSCode.json"=""

[HKEY_CLASSES_ROOT\VSCode.json]
@=".json"

[HKEY_CLASSES_ROOT\VSCode.json\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\json.ico\""

[HKEY_CLASSES_ROOT\VSCode.json\shell]

[HKEY_CLASSES_ROOT\VSCode.json\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.json\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.json\shell\open]

[HKEY_CLASSES_ROOT\VSCode.json\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.json]
@=".json"

[HKEY_CLASSES_ROOT\VSCode.json\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\json.ico\""

[HKEY_CLASSES_ROOT\.html\OpenWithProgids]
"VSCode.html"=""

[HKEY_CLASSES_ROOT\VSCode.html]
@=".html"

[HKEY_CLASSES_ROOT\VSCode.html\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\html.ico\""

[HKEY_CLASSES_ROOT\VSCode.html\shell]

[HKEY_CLASSES_ROOT\VSCode.html\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.html\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.html\shell\open]

[HKEY_CLASSES_ROOT\VSCode.html\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.html]
@=".html"

[HKEY_CLASSES_ROOT\VSCode.html\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\html.ico\""

[HKEY_CLASSES_ROOT\.bower\OpenWithProgids]
"VSCode.bower"=""

[HKEY_CLASSES_ROOT\VSCode.bower]
@=".bower"

[HKEY_CLASSES_ROOT\VSCode.bower\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\bower.ico\""

[HKEY_CLASSES_ROOT\VSCode.bower\shell]

[HKEY_CLASSES_ROOT\VSCode.bower\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.bower\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.bower\shell\open]

[HKEY_CLASSES_ROOT\VSCode.bower\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.bower]
@=".bower"

[HKEY_CLASSES_ROOT\VSCode.bower\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\bower.ico\""

[HKEY_CLASSES_ROOT\.c\OpenWithProgids]
"VSCode.c"=""

[HKEY_CLASSES_ROOT\VSCode.c]
@=".c"

[HKEY_CLASSES_ROOT\VSCode.c\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\c.ico\""

[HKEY_CLASSES_ROOT\VSCode.c\shell]

[HKEY_CLASSES_ROOT\VSCode.c\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.c\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.c\shell\open]

[HKEY_CLASSES_ROOT\VSCode.c\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.c]
@=".c"

[HKEY_CLASSES_ROOT\VSCode.c\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\c.ico\""

[HKEY_CLASSES_ROOT\.config\OpenWithProgids]
"VSCode.config"=""

[HKEY_CLASSES_ROOT\VSCode.config]
@=".config"

[HKEY_CLASSES_ROOT\VSCode.config\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\config.ico\""

[HKEY_CLASSES_ROOT\VSCode.config\shell]

[HKEY_CLASSES_ROOT\VSCode.config\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.config\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.config\shell\open]

[HKEY_CLASSES_ROOT\VSCode.config\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.config]
@=".config"

[HKEY_CLASSES_ROOT\VSCode.config\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\config.ico\""

[HKEY_CLASSES_ROOT\.cpp\OpenWithProgids]
"VSCode.cpp"=""

[HKEY_CLASSES_ROOT\VSCode.cpp]
@=".cpp"

[HKEY_CLASSES_ROOT\VSCode.cpp\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\cpp.ico\""

[HKEY_CLASSES_ROOT\VSCode.cpp\shell]

[HKEY_CLASSES_ROOT\VSCode.cpp\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.cpp\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.cpp\shell\open]

[HKEY_CLASSES_ROOT\VSCode.cpp\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.cpp]
@=".cpp"

[HKEY_CLASSES_ROOT\VSCode.cpp\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\cpp.ico\""

[HKEY_CLASSES_ROOT\.csharp\OpenWithProgids]
"VSCode.csharp"=""

[HKEY_CLASSES_ROOT\VSCode.csharp]
@=".csharp"

[HKEY_CLASSES_ROOT\VSCode.csharp\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\csharp.ico\""

[HKEY_CLASSES_ROOT\VSCode.csharp\shell]

[HKEY_CLASSES_ROOT\VSCode.csharp\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.csharp\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.csharp\shell\open]

[HKEY_CLASSES_ROOT\VSCode.csharp\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.csharp]
@=".csharp"

[HKEY_CLASSES_ROOT\VSCode.csharp\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\csharp.ico\""

[HKEY_CLASSES_ROOT\.css\OpenWithProgids]
"VSCode.css"=""

[HKEY_CLASSES_ROOT\VSCode.css]
@=".css"

[HKEY_CLASSES_ROOT\VSCode.css\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\css.ico\""

[HKEY_CLASSES_ROOT\VSCode.css\shell]

[HKEY_CLASSES_ROOT\VSCode.css\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.css\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.css\shell\open]

[HKEY_CLASSES_ROOT\VSCode.css\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.css]
@=".css"

[HKEY_CLASSES_ROOT\VSCode.css\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\css.ico\""

[HKEY_CLASSES_ROOT\.go\OpenWithProgids]
"VSCode.go"=""

[HKEY_CLASSES_ROOT\VSCode.go]
@=".go"

[HKEY_CLASSES_ROOT\VSCode.go\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\go.ico\""

[HKEY_CLASSES_ROOT\VSCode.go\shell]

[HKEY_CLASSES_ROOT\VSCode.go\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.go\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.go\shell\open]

[HKEY_CLASSES_ROOT\VSCode.go\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.go]
@=".go"

[HKEY_CLASSES_ROOT\VSCode.go\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\go.ico\""

[HKEY_CLASSES_ROOT\.java\OpenWithProgids]
"VSCode.java"=""

[HKEY_CLASSES_ROOT\VSCode.java]
@=".java"

[HKEY_CLASSES_ROOT\VSCode.java\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\java.ico\""

[HKEY_CLASSES_ROOT\VSCode.java\shell]

[HKEY_CLASSES_ROOT\VSCode.java\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.java\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.java\shell\open]

[HKEY_CLASSES_ROOT\VSCode.java\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.java]
@=".java"

[HKEY_CLASSES_ROOT\VSCode.java\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\java.ico\""

[HKEY_CLASSES_ROOT\.javascript\OpenWithProgids]
"VSCode.javascript"=""

[HKEY_CLASSES_ROOT\VSCode.javascript]
@=".javascript"

[HKEY_CLASSES_ROOT\VSCode.javascript\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\javascript.ico\""

[HKEY_CLASSES_ROOT\VSCode.javascript\shell]

[HKEY_CLASSES_ROOT\VSCode.javascript\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.javascript\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.javascript\shell\open]

[HKEY_CLASSES_ROOT\VSCode.javascript\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.javascript]
@=".javascript"

[HKEY_CLASSES_ROOT\VSCode.javascript\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\javascript.ico\""

[HKEY_CLASSES_ROOT\.less\OpenWithProgids]
"VSCode.less"=""

[HKEY_CLASSES_ROOT\VSCode.less]
@=".less"

[HKEY_CLASSES_ROOT\VSCode.less\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\less.ico\""

[HKEY_CLASSES_ROOT\VSCode.less\shell]

[HKEY_CLASSES_ROOT\VSCode.less\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.less\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.less\shell\open]

[HKEY_CLASSES_ROOT\VSCode.less\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.less]
@=".less"

[HKEY_CLASSES_ROOT\VSCode.less\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\less.ico\""

[HKEY_CLASSES_ROOT\.markdown\OpenWithProgids]
"VSCode.markdown"=""

[HKEY_CLASSES_ROOT\VSCode.markdown]
@=".markdown"

[HKEY_CLASSES_ROOT\VSCode.markdown\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\markdown.ico\""

[HKEY_CLASSES_ROOT\VSCode.markdown\shell]

[HKEY_CLASSES_ROOT\VSCode.markdown\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.markdown\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.markdown\shell\open]

[HKEY_CLASSES_ROOT\VSCode.markdown\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.markdown]
@=".markdown"

[HKEY_CLASSES_ROOT\VSCode.markdown\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\markdown.ico\""

[HKEY_CLASSES_ROOT\.python\OpenWithProgids]
"VSCode.python"=""

[HKEY_CLASSES_ROOT\VSCode.python]
@=".python"

[HKEY_CLASSES_ROOT\VSCode.python\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\python.ico\""

[HKEY_CLASSES_ROOT\VSCode.python\shell]

[HKEY_CLASSES_ROOT\VSCode.python\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.python\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.python\shell\open]

[HKEY_CLASSES_ROOT\VSCode.python\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.python]
@=".python"

[HKEY_CLASSES_ROOT\VSCode.python\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\python.ico\""

[HKEY_CLASSES_ROOT\.sql\OpenWithProgids]
"VSCode.sql"=""

[HKEY_CLASSES_ROOT\VSCode.sql]
@=".sql"

[HKEY_CLASSES_ROOT\VSCode.sql\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\sql.ico\""

[HKEY_CLASSES_ROOT\VSCode.sql\shell]

[HKEY_CLASSES_ROOT\VSCode.sql\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.sql\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.sql\shell\open]

[HKEY_CLASSES_ROOT\VSCode.sql\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.sql]
@=".sql"

[HKEY_CLASSES_ROOT\VSCode.sql\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\sql.ico\""

[HKEY_CLASSES_ROOT\.xml\OpenWithProgids]
"VSCode.xml"=""

[HKEY_CLASSES_ROOT\VSCode.xml]
@=".xml"

[HKEY_CLASSES_ROOT\VSCode.xml\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\xml.ico\""

[HKEY_CLASSES_ROOT\VSCode.xml\shell]

[HKEY_CLASSES_ROOT\VSCode.xml\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.xml\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.xml\shell\open]

[HKEY_CLASSES_ROOT\VSCode.xml\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.xml]
@=".xml"

[HKEY_CLASSES_ROOT\VSCode.xml\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\xml.ico\""

[HKEY_CLASSES_ROOT\.typescript\OpenWithProgids]
"VSCode.typescript"=""

[HKEY_CLASSES_ROOT\VSCode.typescript]
@=".typescript"

[HKEY_CLASSES_ROOT\VSCode.typescript\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\typescript.ico\""

[HKEY_CLASSES_ROOT\VSCode.typescript\shell]

[HKEY_CLASSES_ROOT\VSCode.typescript\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.typescript\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.typescript\shell\open]

[HKEY_CLASSES_ROOT\VSCode.typescript\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.typescript]
@=".typescript"

[HKEY_CLASSES_ROOT\VSCode.typescript\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\typescript.ico\""

[HKEY_CLASSES_ROOT\.default\OpenWithProgids]
"VSCode.default"=""

[HKEY_CLASSES_ROOT\VSCode.default]
@=".default"

[HKEY_CLASSES_ROOT\VSCode.default\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\default.ico\""

[HKEY_CLASSES_ROOT\VSCode.default\shell]

[HKEY_CLASSES_ROOT\VSCode.default\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.default\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.default\shell\open]

[HKEY_CLASSES_ROOT\VSCode.default\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.default]
@=".default"

[HKEY_CLASSES_ROOT\VSCode.default\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\default.ico\""

[HKEY_CLASSES_ROOT\.md\OpenWithProgids]
"VSCode.md"=""

[HKEY_CLASSES_ROOT\VSCode.md]
@=".md"

[HKEY_CLASSES_ROOT\VSCode.md\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\markdown.ico\""

[HKEY_CLASSES_ROOT\VSCode.md\shell]

[HKEY_CLASSES_ROOT\VSCode.md\shell\edit]

[HKEY_CLASSES_ROOT\VSCode.md\shell\edit\command]
@="notepad.exe \"%1\""

[HKEY_CLASSES_ROOT\VSCode.md\shell\open]

[HKEY_CLASSES_ROOT\VSCode.md\shell\open\command]
@="\"G:\\Soft\\VSCode\\Code.exe\" \"%1\""

[HKEY_CLASSES_ROOT\VSCode.md]
@=".md"

[HKEY_CLASSES_ROOT\VSCode.md\DefaultIcon]
@="\"G:\\Soft\\VSCode\\resources\\app\\resources\\win32\\markdown.ico\""

Nginx初识【二】

Http代理

Nginx常用反向代理配置规则

反向代理

在http节点下,使用upstream配置服务地址,使用server的location配置代理映射。

Nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream my_server {
server 10.0.0.2:8080;
keepalive 2000;
}
server {
listen 80;
server_name 192.168.0.1;
client_max_body_size 1024M;
#....

location /my/ {
proxy_pass http://my_server/;
proxy_set_header Host $host:$server_port;
}
}

通过该配置,访问nginx地址http://192.168.0.1:80/my的请求会被转发到my_server服务地址http://10.0.0.2:8080/。

需要注意的是,如果按照如下配置:

Nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream my_server {
server 10.0.0.2:8080;
keepalive 2000;
}
server {
listen 80;
server_name 192.168.0.1;
client_max_body_size 1024M;

location /my/ {
proxy_pass http://my_server;
proxy_set_header Host $host:$server_port;
}
}

那么,访问nginx地址http://10.0.0.1:80/my的请求会被转发到my_server服务地址http://10.0.0.2:8080/my。这是因为proxy_pass参数中如果不包含url的路径,则会将location的pattern识别的路径作为绝对路径。

重定向报文代理

即便配置了nginx代理,当服务Response返回重定向报文时(http code为301或302),会将重定向的目标url地址放入http response报文的header的location字段内。用户浏览器收到重定向报文时,会解析出该字段并作跳转。此时新的请求报文将直接发送给服务地址,而非nginx地址。为了能让nginx拦截此类请求,必须修改重定向报文的location信息。

nginx.conf
1
2
3
4
5
6
location /my/ {
proxy_pass http://my_server;
proxy_set_header Host $host:$server_port;

proxy_redirect / /my/;
}

使用proxy_redirect可以修改重定向报文的location字段,例子中会将所有的根路径下的url代理到nginx的/my/路径下返回给用户。比如服务返回的重定向报文的location原始值为/login,那么经过nginx代理后,用户收到的报文的location字段为/my/login。此时,浏览器将会跳转到nginx的/my/login地址进行访问。

需要注意的是,服务返回的重定向报文的location字段有时会填写绝对路径(包含服务的ip/域名和端口),有时候会填写相对路径,此时需要根据实际情况进行甄别。

nginx.conf
1
2
3
4
5
6
location /my/ {
proxy_pass http://my_server;
proxy_set_header Host $host:$server_port;

proxy_redirect http://my_server/ http://$host:$server_port/my/;
}

上述配置便是将my_server服务的根路径下的所有路径代理到nginx地址的/my/路径下。当nginx配置只有一个server时,http://$host:$server_port前缀可以省略。

报文数据替换

使用nginx代理最常见的情况就是http响应报文内写死了服务地址或web绝对路径。写死服务地址的情况比较少见,但也偶尔存在。最棘手的是写死了web绝对路径,尤其是绝对路径都没有公共前缀。举个例子来说:

一般的web页面会包含如下类似路径:

  • /public:用于静态页面资源,如js脚本/public/js,样式表/public/css,图片/public/img等。
  • /static:和/public类似。
  • /api:用于后台服务API接口。
  • /login:用于登录验证。
  • 其他。

对于这样的服务,可能的代理配置如下:

nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location /my/ {
proxy_pass http://my_server/;
proxy_set_header Host $host:$server_port;

proxy_redirect / /my/;
}
location /login/ {
proxy_pass http://my_server/public;
proxy_set_header Host $host:$server_port;
}
location /public/ {
proxy_pass http://my_server/public;
proxy_set_header Host $host:$server_port;
}
location /api/ {
proxy_pass http://my_server/api;
proxy_set_header Host $host:$server_port;
}

由于web页面或静态资源内写死了类似的绝对路径,那么对于用户来说,通过页面内的链接进行跳转时,都会请求到nginx服务对应的路径上。一旦存在另一个服务也包含类似的路径,也需要nginx进行代理,那么矛盾就出现了:访问nginx的同一个路径下的请求究竟转发给哪一个服务?

要解决这个问题,必须在用户收到报文前,将报文的数据中包含的绝对路径都添加统一的前缀,如/my/public,/my/api,/my/login,这样nginx代理配置则可以简化为:

nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
location /my/ {
proxy_pass http://my_server/;
proxy_set_header Host $host:$server_port;

proxy_redirect / /my/;
}
location /other/ {
proxy_pass http://other_server/;
proxy_set_header Host $host:$server_port;

proxy_redirect / /other/;
}

nginx的ngx_http_sub_module模块提供了类似的报文数据替换功能,该模块默认不会安装,需要在编译nginx时添加–with-http_sub_module参数,或者直接下载nginx的rpm包。

使用sub_filter对数据包进行替换的语法如下:

nginx.conf
1
2
3
4
5
6
7
8
9
10
11
location /my/ {
proxy_pass http://my_server/;
proxy_set_header Host $host:$server_port;

sub_filter 'href="/' 'href="/my/';
sub_filter 'src="/' 'src="/my/';
#sub_filter '10.170.24.244:7957' $host:$server_port;
#sub_filter_types application/json application/x-javascript text/plain application/javascript;
sub_filter_types text/html;
sub_filter_once off;
}

上述配置会将/my/下的所有响应报文内容的href=”/替换为href=”/my,以及src=”/替换为src=”/my,即为所有的绝对路径添加公共前缀。

注意,如果需要配置多个sub_filter,必须保证nginx是1.9.4版本之上的。

即便如此,sub_filter也不能解决所有问题。目前流行的js框架都会有自动渲染url的功能,也就是说,很多绝对路径并非写死在静态页面内,也是由js代码框架动态生成的,面对这样的情况,sub_filter也是无能为力了。对于这样的情况,笔者只能由衷地奉劝,还是安静的改代码吧!

Nginx配置SSL转发代理

下列配置Nginx通过8406端口SSL转发代理http://192.168.2.17:8407

nginx.conf
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
http {
...
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...

server{
listen 8406 ssl;
server_name localhost;
# SSL
ssl_certificate cert/192-168-2-17_LIS.crt;
ssl_certificate_key cert/192-168-2-17_LIS.key;
ssl_trusted_certificate cert/192-168-2-17_RootCA.crt;
proxy_read_timeout 2400s;

location /{
# proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://192.168.2.17:8407;
proxy_set_header X-Request-URI $scheme://$host:$server_port$request_uri;
proxy_redirect http://192.168.2.17:8407 https://$host:$server_port;
}
error_page 497 https://$host:$server_port$request_uri;
}
...
}

笔记

重定向失败

原因:未带端口转发

关键代码:proxy_set_header Host $host:$server_port;

参考:

https://www.kancloud.cn/qq13867685/openresty-api-cn/159026
https://blog.csdn.net/QIU176161650/article/details/124948351

持久化Gist代码raw链接

问题

通常,Gist 文件的 raw 链接会随着版本二更改,但在使用上往往不便,因此需要持久化文件的 raw 链接地址。

解决方法

获得 Gist 文件列表中的第一个文件: https://gist.github.com/gist_user/gist_id/raw/

例如: https://gist.github.com/atenni/5604522/raw/

即便更改了文件名,上述方法依然可以获得列表中的第一个文件。

获得多个文件: https://gist.github.com/gist_user/gist_id/raw/file_name

例如: https://gist.github.com/atenni/5604522/raw/README.md

参考

管理Chrome通过组策略

前言

Disable “Print…” in Context menu of selected text in Chrome

从该回答中获取到提示,使用chrome的组策略文件管理一些在chrome://flags中无法找到的一些功能选项。
策略文件下载地址:https://chromeenterprise.google/browser/download/#manage-policies-tab

rar压缩包内的结构:

tree.bat
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
policy_templates
│ VERSION

├─chromeos
│ └─admx
│ │ chromeos.admx
│ │ google.admx
│ │
│ ├─de-DE
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─en-US
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─es-419
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─es-ES
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─fr-FR
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─id-ID
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─it-IT
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─ja-JP
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─ko-KR
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─nl-NL
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─pt-BR
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─ru-RU
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─th-TH
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─tr-TR
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─uk-UA
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─vi-VN
│ │ chromeos.adml
│ │ google.adml
│ │
│ ├─zh-CN
│ │ chromeos.adml
│ │ google.adml
│ │
│ └─zh-TW
│ chromeos.adml
│ google.adml

├─common
│ └─html
│ ├─de-DE
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─en-US
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─es-419
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─es-ES
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─fr-FR
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─id-ID
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─it-IT
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─ja-JP
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─ko-KR
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─nl-NL
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─pt-BR
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─ru-RU
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─th-TH
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─tr-TR
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─uk-UA
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─vi-VN
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ ├─zh-CN
│ │ chrome_policy_atomic_groups_list.html
│ │ chrome_policy_list.html
│ │
│ └─zh-TW
│ chrome_policy_atomic_groups_list.html
│ chrome_policy_list.html

└─windows
├─adm
│ ├─de-DE
│ │ chrome.adm
│ │
│ ├─en-US
│ │ chrome.adm
│ │
│ ├─es-419
│ │ chrome.adm
│ │
│ ├─es-ES
│ │ chrome.adm
│ │
│ ├─fr-FR
│ │ chrome.adm
│ │
│ ├─id-ID
│ │ chrome.adm
│ │
│ ├─it-IT
│ │ chrome.adm
│ │
│ ├─ja-JP
│ │ chrome.adm
│ │
│ ├─ko-KR
│ │ chrome.adm
│ │
│ ├─nl-NL
│ │ chrome.adm
│ │
│ ├─pt-BR
│ │ chrome.adm
│ │
│ ├─ru-RU
│ │ chrome.adm
│ │
│ ├─th-TH
│ │ chrome.adm
│ │
│ ├─tr-TR
│ │ chrome.adm
│ │
│ ├─uk-UA
│ │ chrome.adm
│ │
│ ├─vi-VN
│ │ chrome.adm
│ │
│ ├─zh-CN
│ │ chrome.adm
│ │
│ └─zh-TW
│ chrome.adm

├─admx
│ │ chrome.admx
│ │ google.admx
│ │
│ ├─de-DE
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─en-US
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─es-419
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─es-ES
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─fr-FR
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─id-ID
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─it-IT
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─ja-JP
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─ko-KR
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─nl-NL
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─pt-BR
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─ru-RU
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─th-TH
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─tr-TR
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─uk-UA
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─vi-VN
│ │ chrome.adml
│ │ google.adml
│ │
│ ├─zh-CN
│ │ chrome.adml
│ │ google.adml
│ │
│ └─zh-TW
│ chrome.adml
│ google.adml

└─examples
chrome.reg

打开policy_templates\common\html\zh-CN\chrome_policy_list.html,查找自己需要控制的选项,打开regedit添加对应的项。

关闭菜单右键的分享页面

选项说明:policy_templates/common/html/zh-CN/chrome_policy_list.html#DesktopSharingHubEnabled
根据文档描述,关闭该功能的Reg如下:

DesktopSharingHubEnabled.reg
1
2
3
4
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Policies\Google\Chrome]
"DesktopSharingHubEnabled"=dword:00000000

git彻底移除敏感文件

前言

在日常开发项目中,可能会出现将包含数据库连接字符、中间件密钥等敏感信息提交并推送到远程仓库的情况,这时需要将文件删除。执行git rm config.json命令虽然删除了文件,但是在历史提交记录中仍然可以查看到数据内容。这时可以使用 核武器级选项:filter-branch

移除数据

filter-branch

描述

允许您通过重写 <rev-list options> 中提到的分支来重写 Git 修订历史,在每个修订上应用自定义过滤器。这些过滤器可以修改每棵树(例如删除文件或对所有文件运行 perl 重写)或有关每次提交的信息。否则,将保留所有信息(包括原始提交时间或合并信息)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 移除test文件夹下config.json 文件,并擦洗所有涉及此文件的提交历史。
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch test/config.json' --prune-empty --tag-name-filter cat -- --all

# 移除test文件夹下所有文件,并擦洗所有涉及此文件的提交历史。
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch test' --prune-empty --tag-name-filter cat -- --all

# 当你检查项目后,发现没有任何问题,则将命令提交到版本库中。
git push origin --force --all

# 你还需要提交你的git tags,用以更新服务器的git tags。
git push origin --force --tags

# 删除本地缓存
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

命令说明:git filter-branch

option

1
2
--f 
--forece

git filter-branch 拒绝以现有的临时目录开始,或者当已经使用 refs / original / 开始refs时,除非被强制。

1
--index-filter <command>

这是重写索引的过滤器。它类似于树过滤器,但不检查树,这使得它更快。经常与git rm –cached –ignore-unmatch …一起使用

1
--prune-empty

某些过滤器将生成空提交,使树保持不变。如果git-filter-branch只有一个或零个非修剪父项,则该选项指示git-filter-branch删除这些提交;因此,合并提交将保持不变。此选项不能与--commit-filter一起使用,但通过在提交过滤器中使用提供的git_commit_non_empty_tree功能可以实现相同的效果。

1
--tag-name-filter <command>

这是用于重写标记名称的过滤器。传递时,将为每个指向重写对象(或指向重写对象的标记对象)的标记ref调用它。原始标记名称通过标准输入传递,新标记名称在标准输出上是预期的。
原始标签不会被删除,但可以被覆盖;使用“—tag-name-filter cat”来简单地更新标签。在这种情况下,请务必小心并确保备份旧标签,以防转换发生冲突。
支持几乎正确的标记对象重写。如果标记附加了消息,则将使用相同的消息,作者和时间戳创建新的标记对象。如果标签附有签名,则签名将被删除。根据定义,不可能保留签名。这是“几乎”正确的原因,因为理想情况下,如果标签没有改变(指向同一个对象,具有相同的名称等),它应该保留任何签名。情况并非如此,签名将永远删除,买家要小心。也不支持更改作者或时间戳(或标记消息)。指向其他标记的标记将被重写以指向底层提交。

缩小存储库的清单

git-filter-branch可用于删除文件的子集,通常使用–index-filter和–subdirectory-filter的某种组合。人们期望生成的存储库小于原始存储库,但是你需要更多的步骤来实际使它变小,因为Git努力不会丢失你的对象,直到你告诉它。首先要确保:

  • 如果blob在其生命周期内被移动,那么您确实删除了文件名的所有变体。 git log –name-only –follow –all – filename可以帮助您找到重命名。
  • 你真的过滤了所有的refs:在调用git-filter-branch时使用–tag-name-filter cat – –all。
    然后有两种方法可以获得更小的存储库。更安全的方法是克隆,保持原始原封不动。

用git clone file:///path/to/repo克隆它。克隆将没有删除的对象。参见 git-clone [1] 。 (请注意,使用普通路径进行克隆只会将所有内容硬链接!)

忽略文件更新

  1. 情况:始终不需要git跟踪本地的一些文件
    • 方法:使用.gitignore文件忽略
    • 使用git init操作创建git控制管理之后,默认不会生成.gitignore文件。我们可以创建该文件,将对应的不需要的文件名或文件夹名添加进去。后面再使用git add .对所有新增文件更新到 git管理系统时不会追踪.gitignore中的文件,也不会在使用git status操作时有提示。
    • .gitignore适合添加一些IDE的配置文件,避免自己的配置文件在于他人协作或者项目迁移时产生影响。也适合添加编译生成的一些中间文件,以便保证git中添加的均为源代码。
    • 需要注意的是.gitignore是用于管理不在index tree的文件,如果不小心将文件添加了进去,可以先使用git rm --cached filename命令将文件从托管中移除(不会删除文件本身),.gitignore就会生效。
  2. 情况:不需要将文件以后的更改更新到git,但是需要保留目前git中文件的状态
    • 方法:git update-index --assume-unchanged filename
    • 该操作标记文件,该文件后续的变化都不会更新到index tree。
    • 如果需要恢复对文件的版本控制,执行以下操作: git update-index --no-assume-unchanged filename

Note

du -hs <flie/folder>:查询文件/文件夹占用大小

参考:

Git 工具 - 重写历史
Git移除敏感数据
Linux du 命令
git使用-忽略文件更新的几种方法

WSDL文件结构分析

WSDL是什么?

WSDL 是一种可用于定义Web服务的语言
WSDL 是用 XML 编写的
WSDL 定义描述了如何访问 Web 服务以及它将执行什么操作。
WSDL 代表Web Services Description Language(网络服务描述语言)
WSDL 是 2007 年 6 月 26 日的 W3C 推荐标准

到目前为止已发布了2个主要版本,它们分别如下所述:

在高层次上,WSDL是一种允许编写WSDL文档的语言,因此:

WSDL文档可以定义一组Web服务。
Web服务可以定义为接口和一组端点。
端点可以定义为地址和绑定。
可以定义地址以告知提供服务的位置。
可以定义绑定以告知如何格式化和传输消息。
接口可以定义为一组操作。
操作可以定义为输入和输出消息序列。

Alt text

Alt text

WSDL用来干什么的?

WSDL(Web Service Description Language)用XML格式的文件来描述可用的Web服务。

WSDL文件被用来在Web Service生产者和消费者之间交流接口信息。

其实说白了就是一个标准,终端按照这个标准在网络中创建Web Service,客户端也按照此标准去连接这个服务,并且根据WSDL文件获知自己所需要的操作,客户端可以在不了解Web Service的实现细节的情况下使用Web Service的能力。

WSDL发展过程

WSDL 1.0(2000年9月)是由IBM、微软和Ariba开发的,用于描述其SOAP工具包的Web服务。它是由两种服务描述语言结合而成的。IBM的NASSL(网络应用服务规范语言)和微软的SDL(服务描述语言)。

2001年3月发表的WSDL 1.1是WSDL 1.0的形式化。在1.0和1.1之间没有引入重大变化。

WSDL 1.2(2003年6月)是W3C的一个工作草案,但已经成为WSDL 2.0。根据W3C的说法。WSDL 1.2 对开发者来说比以前的版本更容易、更灵活。WSDL 1.2试图删除不具互操作性的功能,也更好地定义了HTTP 1.1绑定。WSDL 1.2不被大多数SOAP服务器/供应商所支持。

WSDL 2.0在2007年6月成为W3C的建议。WSDL 1.2被重新命名为WSDL 2.0,因为它与WSDL 1.1有很大的区别。这些变化如下。

为描述语言添加了进一步的语义
删除了message结构
不支持操作符重载
PortTypes 重命名为interfaces
Ports重命名为endpoints

所以说现在WSDL流行的两个版本是WSDL2.0 和 WSDL1.1。虽说WSDL2.0 是W3C推荐的版本,但是现在大多数的厂商支持的还是WSDL1.1。

WSDL1.1 和WSDL2.0

WSDL 1.1 规范仅定义描述如何结合 SOAP 1.1、HTTP GET 和 POST 以及 MIME 使用 WSDL 的绑定。

WSDL 2.0 提供了一种模型和 XML 格式来描述 Web 服务。它使您能够将服务提供的抽象功能的描述与服务描述的具体细节分开,例如提供该功能的“方式”和“位置”。它还描述了消息交换模式的扩展、SOAP 模块以及用于描述 SOAP 1.2 和 HTTP 的此类具体细节的语言。 WSDL 2.0 规范还解决了 WSDL 1.1 中存在的许多技术问题和限制。

WSDL 1.1 规范由万维网联盟 (W3C)作为 WSDL 版本 1.1 的 W3C 注释发布。

WSDL 2.0 的规范在WSDL 2.0 版中作为 W3C 推荐标准发布。

WSDL 用法

WSDL 通常与 SOAP 和 XML Schema 结合使用,以在 Internet 上提供 Web 服务。连接到 Web 服务的客户端程序可以读取 WSDL 以确定服务器上可用的功能。使用的任何特殊数据类型都以 XML 模式的形式嵌入到 WSDL 文件中。然后客户端可以使用 SOAP 实际调用 WSDL 中列出的函数之一。

WSDL 文档包含客户端调用 Web Service方法所需的所有信息:

  • 作为方法参数或返回值的数据类型
  • 各个方法的名称和签名(WSDL把方法称为操作)
  • 每个方法允许的协议和消息格式
  • 用于访问 Web Service的 URL

WSDL 文档

WSDL 将 Web Service分解为三个特定的、可识别的元素,这些元素一旦定义就可以组合或重用。

可以单独定义的 WSDL 的三个主要元素是:

  • Types
  • Operations
  • Binding

一个 WSDL 文档有各种元素,但它们都包含在这三个主要元素中,它们可以作为单独的文档开发,然后它们可以组合或重用以形成完整的 WSDL 文件。

WSDL 元素

WSDL 1.0

WSDL2.0

https://www.iteye.com/blog/jameswxx-250759

https://www.cnblogs.com/si-shaohua/archive/2012/04/28/2475257.html

https://www.daimajiaoliu.com/daima/47dcc29ff900403

Lua初识【一】

b站bug根因.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local _gcd
_gcd = function(a,b)
print("a:",a,"b:",b)
print("b == 0",b == 0)

if b == 0 then
return a
end

return _gcd(b,a%b)
end

print(50 /0 ) -- inf
print(50%'0') -- n%0

print("first :_gcd(52,0):",_gcd(50,'0'))
print("second :_gcd('0',50%'0'):",_gcd('0',50%'0'))

清理IIS日志文件

管理 IIS 日志文件存储

通过脚本删除旧日志文件

您可以通过运行脚本来控制日志文件的磁盘使用情况,该脚本会自动删除超过特定年龄的日志文件。在计划任务中运行此脚本将控制磁盘填满问题,而无需持续维护。

以下 VBScript 将检查文件夹中每个日志文件的年龄,并将删除任何早于指定年龄的日志文件。要根据您的目的自定义脚本,只需在脚本的第 1 行中更改文件夹的名称和路径,并在第 2 行中将最大使用期限更改为所需的天数。

retentionscript.vbs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sLogFolder = "c:\inetpub\logs\LogFiles"
iMaxAge = 30 'in days
Set objFSO = CreateObject("Scripting.FileSystemObject")
set colFolder = objFSO.GetFolder(sLogFolder)
For Each colSubfolder in colFolder.SubFolders
Set objFolder = objFSO.GetFolder(colSubfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
iFileAge = now-objFile.DateCreated
if iFileAge > (iMaxAge+1) then
objFSO.deletefile objFile, True
end if
Next
Next

上面的脚本将扫描所有子文件夹,因此它将处理指定文件夹中和下的所有站点的日志。如果您想将该过程限制为单个站点,请适当更改路径。

要手动运行脚本,请在管理员命令行中执行以下脚本:cscript.exe c:\scripts\retentionscript.vbs

跑vbs脚本的bat,不用再输入文件路径,只需要bat和vbs文件在同一目录就行:

cleanup.bat
1
2
3
4
5
6
7
8
@echo off
echo 当前盘符和路径:%~dp0
echo on
@cd /d %~dp0
cscript.exe retentionscript.vbs
@echo off
echo 清理日志完成
pause

出处:
Delete Old Log Files by Script

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×