質問編集履歴

2

サンプルコードの追加

2020/01/31 05:41

投稿

ryoyai
ryoyai

スコア5

test CHANGED
File without changes
test CHANGED
@@ -151,3 +151,383 @@
151
151
  アドバイスいただければ幸いです。
152
152
 
153
153
  よろしくお願いいたします。
154
+
155
+
156
+
157
+ # 追記:サンプルコード
158
+
159
+
160
+
161
+ ご指摘を受け、実際のプログラムの挙動に似せたものをサンプルコードとして作成してみました。
162
+
163
+
164
+
165
+ これを作っている過程で気づいたのですが、このプログラムは**グローバル変数としてキャッシュ**を持っています。
166
+
167
+ そのキャッシュデータに対する同時アクセス制御(`mutex`)に問題があるのではないかと思い、`mutex`まわりをいくつか修正してみたところ、停止現象がかなり減った感じがしています。
168
+
169
+ そのため現時点ではグローバル変数への同時アクセスが影響しているのではないかと疑っています。
170
+
171
+ (ただし、それがF5で解消するというのもよく分からない話のように思え、この点の疑問は残っています)
172
+
173
+
174
+
175
+
176
+
177
+ **実際のプログラムに似せるため、プログラム内にファイルシステムへのアクセスが存在します。ご注意お願いします。**
178
+
179
+ ```go
180
+
181
+ package main
182
+
183
+
184
+
185
+ import (
186
+
187
+ "bufio"
188
+
189
+ "encoding/json"
190
+
191
+ "io/ioutil"
192
+
193
+ "log"
194
+
195
+ "net/http"
196
+
197
+ "os"
198
+
199
+ "path"
200
+
201
+ "strconv"
202
+
203
+ "sync"
204
+
205
+
206
+
207
+ "github.com/gorilla/mux"
208
+
209
+ )
210
+
211
+
212
+
213
+ var (
214
+
215
+ DataCache = map[string]string{}
216
+
217
+ Datapath string
218
+
219
+ mutex sync.RWMutex
220
+
221
+ )
222
+
223
+
224
+
225
+ type res_ping struct {
226
+
227
+ Msg string `json:"msg"`
228
+
229
+ }
230
+
231
+
232
+
233
+ func GetPing(w http.ResponseWriter, r *http.Request) {
234
+
235
+ log.Println("GetPingStart")
236
+
237
+ defer log.Println("GetPingEnd")
238
+
239
+
240
+
241
+ res := res_ping{Msg: "server_alive"}
242
+
243
+ b, _ := json.Marshal(res)
244
+
245
+ w.Write(b)
246
+
247
+ }
248
+
249
+
250
+
251
+ type res_get struct {
252
+
253
+ Msg string `json:"msg"`
254
+
255
+ }
256
+
257
+
258
+
259
+ func GetData(w http.ResponseWriter, r *http.Request) {
260
+
261
+ log.Println("GetDataStart")
262
+
263
+ defer log.Println("GetDataEnd")
264
+
265
+
266
+
267
+ line, _ := mux.Vars(r)["line"]
268
+
269
+
270
+
271
+ if line == "" {
272
+
273
+ line = "0"
274
+
275
+ }
276
+
277
+ mutex.RLock()
278
+
279
+ msg := DataCache[line]
280
+
281
+ mutex.RUnlock()
282
+
283
+
284
+
285
+ res := res_get{Msg: msg}
286
+
287
+ b, _ := json.Marshal(res)
288
+
289
+ w.Write(b)
290
+
291
+
292
+
293
+ }
294
+
295
+
296
+
297
+ type req_post struct {
298
+
299
+ Data string `json:"data"`
300
+
301
+ }
302
+
303
+
304
+
305
+ type res_post struct {
306
+
307
+ Msg string `json:"msg"`
308
+
309
+ }
310
+
311
+
312
+
313
+ func PostData(w http.ResponseWriter, r *http.Request) {
314
+
315
+ log.Println("PostDataStart")
316
+
317
+ defer log.Println("PostDataEnd")
318
+
319
+
320
+
321
+ body := r.Body
322
+
323
+ defer body.Close()
324
+
325
+ b, _ := ioutil.ReadAll(body)
326
+
327
+ req := req_post{}
328
+
329
+ _ = json.Unmarshal(b, &req)
330
+
331
+ data := req.Data
332
+
333
+
334
+
335
+ mutex.Lock()
336
+
337
+ defer mutex.Unlock()
338
+
339
+ file, _ := os.OpenFile(Datapath, os.O_WRONLY|os.O_APPEND, 0666)
340
+
341
+ defer file.Close()
342
+
343
+ file.WriteString(data + "\n")
344
+
345
+ file.Close()
346
+
347
+ readdata()
348
+
349
+
350
+
351
+ res := res_post{Msg: "OK"}
352
+
353
+ rb, _ := json.Marshal(res)
354
+
355
+ w.Write(rb)
356
+
357
+
358
+
359
+ }
360
+
361
+
362
+
363
+ func SetJsonheader(w http.ResponseWriter) {
364
+
365
+ w.Header().Set("Content-Type", "application/json")
366
+
367
+ }
368
+
369
+
370
+
371
+ func Wrap(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
372
+
373
+ return func(w http.ResponseWriter, r *http.Request) {
374
+
375
+ EnableCors(&w)
376
+
377
+ SetJsonheader(w)
378
+
379
+ f(w, r)
380
+
381
+ }
382
+
383
+ }
384
+
385
+
386
+
387
+ func EnableCors(w *http.ResponseWriter) {
388
+
389
+ (*w).Header().Set("Access-Control-Allow-Origin", "http://localhost:8004")
390
+
391
+ (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
392
+
393
+ (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
394
+
395
+ }
396
+
397
+
398
+
399
+ func setup() {
400
+
401
+ log.Println(Datapath)
402
+
403
+ file, err := os.Create(Datapath)
404
+
405
+ if err != nil {
406
+
407
+ log.Fatal(err)
408
+
409
+ }
410
+
411
+ defer file.Close()
412
+
413
+ // 実際の挙動に近づけるためにファイル書き込み(データ多め)をおこなっています。問題があれば適宜修正してください。
414
+
415
+ for i := 0; i < 10000; i++ {
416
+
417
+ _, _ = file.WriteString("data898999898989898998989ddddd\n")
418
+
419
+ }
420
+
421
+ file.Close()
422
+
423
+
424
+
425
+ readdata()
426
+
427
+ //DataCache["0"] = "data0"
428
+
429
+ //DataCache["1"] = "data1"
430
+
431
+ //DataCache["2"] = "data2"
432
+
433
+ }
434
+
435
+
436
+
437
+ func readdata() {
438
+
439
+ file, _ := os.Open(Datapath)
440
+
441
+ defer file.Close()
442
+
443
+ sc := bufio.NewScanner(file)
444
+
445
+ count := 0
446
+
447
+ for sc.Scan() {
448
+
449
+ DataCache[strconv.Itoa(count)] = sc.Text()
450
+
451
+ count++
452
+
453
+ }
454
+
455
+ }
456
+
457
+
458
+
459
+ func main() {
460
+
461
+
462
+
463
+ datadir := os.TempDir()
464
+
465
+ datapath := path.Join(datadir, "data_6f3eb709jlgq0w2h.txt")
466
+
467
+ Datapath = datapath
468
+
469
+ setup()
470
+
471
+ defer os.Remove(datapath)
472
+
473
+
474
+
475
+ r := mux.NewRouter()
476
+
477
+ r.HandleFunc("/ping", Wrap(GetPing)).Methods("GET", "POST", "OPTIONS")
478
+
479
+ r.HandleFunc("/data/{line}", Wrap(GetData)).Methods("GET", "OPTIONS")
480
+
481
+ r.HandleFunc("/data", Wrap(GetData)).Methods("GET", "OPTIONS")
482
+
483
+ r.HandleFunc("/data", Wrap(PostData)).Methods("POST", "OPTIONS")
484
+
485
+
486
+
487
+ srv := http.Server{
488
+
489
+ Addr: ":48000",
490
+
491
+ Handler: r,
492
+
493
+ TLSConfig: nil,
494
+
495
+ ReadTimeout: 0,
496
+
497
+ ReadHeaderTimeout: 0,
498
+
499
+ WriteTimeout: 0,
500
+
501
+ IdleTimeout: 0,
502
+
503
+ MaxHeaderBytes: 0,
504
+
505
+ TLSNextProto: nil,
506
+
507
+ ConnState: nil,
508
+
509
+ ErrorLog: nil,
510
+
511
+ BaseContext: nil,
512
+
513
+ ConnContext: nil,
514
+
515
+ }
516
+
517
+ log.Println("start")
518
+
519
+ srv.SetKeepAlivesEnabled(false)
520
+
521
+ err := srv.ListenAndServe()
522
+
523
+ if err != nil {
524
+
525
+ log.Fatalf(err.Error())
526
+
527
+ }
528
+
529
+ }
530
+
531
+
532
+
533
+ ```

1

fetchを使用している点を追記

2020/01/31 05:41

投稿

ryoyai
ryoyai

スコア5

test CHANGED
File without changes
test CHANGED
@@ -120,7 +120,7 @@
120
120
 
121
121
 
122
122
 
123
- リクエストはブラウザから送る場合でも、ツール(postmanを使っています)で送る場合でも発生します。
123
+ リクエストはブラウザ(`fetch`を使用)から送る場合でも、ツール(`postman`を使)で送る場合でも発生します。
124
124
 
125
125
  発生頻度はそれなりに高く、リクエスト数十回に1回くらい見かける印象です(プロダクトでこの頻度だと使い物にならないと思います)。
126
126