Skip to content

Instantly share code, notes, and snippets.

@nullsimon
Created December 9, 2020 15:29
Show Gist options
  • Save nullsimon/258ded650969d4bc9f47d46f901b68c6 to your computer and use it in GitHub Desktop.
Save nullsimon/258ded650969d4bc9f47d46f901b68c6 to your computer and use it in GitHub Desktop.
Multi-threaded concurrency http client golang version
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"runtime"
"time"
)
var (
httpClient *http.Client
content []string
fail []string
)
const (
//MaxIdleConnections 2
MaxIdleConnections int = 200
//RequestTimeout 2
RequestTimeout int = 30
//WORKERNUM concurrent goroutine
WORKERNUM int = 200
//CPUNUM max cpu num
CPUNUM int = 4
//JOBS all jobs num
JOBS int = 10 * 10000
//PROGRESS OLD
PROGRESS int = 0
)
func createHTTPClient() *http.Client {
client := &http.Client{
Transport: &http.Transport{
MaxIdleConnsPerHost: MaxIdleConnections,
},
Timeout: time.Duration(RequestTimeout) * time.Second,
}
return client
}
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Println("worker", id, "started job", j)
testCPU(j)
fmt.Println("worker", id, "finished job", j)
results <- j * 2
}
}
func init() {
runtime.GOMAXPROCS(CPUNUM)
httpClient = createHTTPClient()
content = readLine("/tmp/hello.txt", PROGRESS)
}
func main() {
jobs := make(chan int, JOBS)
results := make(chan int, JOBS)
for w := 1; w <= WORKERNUM; w++ {
go worker(w, jobs, results)
}
for j := 1; j <= JOBS; j++ {
jobs <- j
}
close(jobs)
for a := 1; a <= JOBS; a++ {
<-results
}
fmt.Println(fail)
}
func fetch(targetURL string, postData url.Values) (string, error) {
var request *http.Request
postDataStr := postData.Encode()
postDataBytes := []byte(postDataStr)
postBytesReader := bytes.NewReader(postDataBytes)
request, _ = http.NewRequest("POST", targetURL, postBytesReader)
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
response, fetchError := httpClient.Do(request)
if fetchError != nil {
return "", fetchError
}
defer response.Body.Close()
body, readError := ioutil.ReadAll(response.Body)
if readError != nil {
return "", readError
}
return string(body), nil
}
func testCPU(lineNumber int) {
targetURL := "https://example.com/"
if lineNumber >= len(content) {
return
}
question := url.Values{"apikey": {"something"}, "text": {content[lineNumber-1]}}
if _, err := fetch(targetURL, question); err != nil {
fail = append(fail, content[lineNumber-1])
}
}
func readLine(file string, progress int) []string {
fi, err := os.Open(file)
if err != nil {
fmt.Printf("Error: %s\n", err)
return nil
}
defer fi.Close()
br := bufio.NewReader(fi)
var slice []string
i := 0
for {
a, _, c := br.ReadLine()
i++
if c == io.EOF {
break
}
fmt.Println(string(a))
if i <= progress {
continue
}
slice = append(slice, string(a))
}
return slice
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment