1 / 42

Пишем функциональное, надежное и быстрое веб-приложение на Go

Дмитрий Вьюков, dvyukov@ Google. Пишем функциональное, надежное и быстрое веб-приложение на Go. План. Зачем новый язык? Привет, Мир! Пишем веб-приложение Инструментарий. История. Конец 2007: Rob Pike, Ken Thompson и RobertGriesemer начали проектировать Ноябрь 2009: open-source release

bucknerj
Download Presentation

Пишем функциональное, надежное и быстрое веб-приложение на Go

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Дмитрий Вьюков, dvyukov@ Google Пишем функциональное, надежное и быстрое веб-приложение на Go

  2. План • Зачем новый язык? • Привет, Мир! • Пишем веб-приложение • Инструментарий

  3. История • Конец 2007: Rob Pike, Ken Thompson и RobertGriesemer начали проектировать • Ноябрь 2009: open-source release • Март 2012: релиз Go1 • Go1.1, Go1.2, Go1.3

  4. Зачем? Дизайн мотивирован нашими нуждами в Google: • Large-scale системы • Large-scale разработка • Время сборки • Эффективность • Масштабируемость • Concurrency • Безопасность

  5. Что такое Go? • Простой язык, который легко изучить и читать • Статически-типизированный, но “чувствуется” как динамический • Компилируется в машинный код, но быстрая разработка • Быстрый и масштабируемый • Сборка мусора • Встроенная поддержка concurrency • Стандартная библитека “с включенными батарейками” • Open-source (400+ контрибьюторов)

  6. Кто использует? • Google: dl.google.co • Google: vitess (MySQL scaling) • Google: flywheel (mobile proxy) • BBC Worldwide • Canonical • Heroku • Nokia • SoundCloud • Apple • Yandex • BitBucket • dotCloud • github • gov.uk • Heroku • Intel • Iron.io • Mozilla • Percona • Zynga • Docker • Packer

  7. Крэш-курс

  8. Привет, Мир! • package main • import "fmt" • func main() { • fmt.Printf("Привет, Мир!\n") • }

  9. Привет, Net! • func main() { • ln, err := net.Listen("tcp", "localhost:11500") • if err != nil { • log.Fatal(err) • } • for { • c, err := ln.Accept() • if err != nil { • log.Fatal(err) • } • fmt.Fprintf(c, "Привет, Net!\n") • c.Close() • } • }

  10. Интерфейсы • fmt.Fprintf(c, "Привет, Net!\n") • Duck typing! • type Writer interface { • Write(p []byte) (n int, err error) • } • type netFD struct {...} • func (fd *netFD) Write(p []byte) (nn int, err error)

  11. Эхо-сервер func main() { ln, err := net.Listen("tcp", "localhost:11500") if err != nil { log.Fatal(err) } for { c, err := ln.Accept() if err != nil { log.Fatal(err) } io.Copy(c, c) } }

  12. Привет, concurrency! func main() { ln, err := net.Listen("tcp", "localhost:11500") if err != nil { log.Fatal(err) } for { c, err := ln.Accept() if err != nil { log.Fatal(err) } go io.Copy(c, c) } }

  13. Сoncurrency Горутины: go doFoo(a, b) go conn.Handle() go func() { doFoo(a, b) notifyCompletion() }()

  14. Channels Каналы: c := make(chan int) c <- 42 fmt.Println(<-c)

  15. Select select { case inChan <- v: fmt.Println("Отправлено") case <-timeoutChan: fmt.Println("Потрачено") }

  16. Запрос нескольких бэкендов • func multiGet(urls []string) (results []*http.Response) { • res := make(chan *http.Response) • for _, url := range urls { • go func(url string) { • resp, _ := http.Get(url) • res <- resp • }(url) • } • for _ = range urls { • results = append(results, <-res) • } • return • }

  17. Запрос с таймаутом • t := time.After(time.Second) • for _ = range urls { • select { • case resp := <-res: • results = append(results, resp) • case <-t: • return • } • }

  18. Файловер • func getFailover(primary, secondary string) *http.Response { • res := make(chan *http.Response, 1) • go func() { • res <- requestServer(primary) • }() • select { • case resp := <-res: • return resp • case <-time.After(50 * time.Millisecond): • } • go func() { • res <- requestServer(secondary) • }() • return <-res • }

  19. Батарейки включены encoding/{json, xml, gob, base64} compress/{gzip, bzip2, flate} crypto/{aes, des, sha1, tls, x509} net/{http, rpc, smtp} database/sql html/template regexp flag

  20. В бой!

  21. Флаги • package main • import "flag" • var ( • httpAddr = flag.String("http", ":8080", "address to serve http") • apiAddr = flag.String("api", ":8081", "address to serve api") • ) • func main() { • flag.Parse() • ...

  22. HTTP сервер • import "net/http" • func main() { • ... • http.HandleFunc("/", handleWelcome) • http.HandleFunc("/chat", handleChat) • go http.ListenAndServe(*httpAddr, nil) • ...

  23. Websocket сервер • import "code.google.com/p/go.net/websocket" • func main() { • ... • http.Handle("/ws", • websocket.Handler(handleWebsocket)) • ...

  24. API сервер • import "net" • func main() { • ... • ln, err := net.Listen("tcp", *apiAddr) • if err != nil { • log.Fatal(err) • } • go func() { • for { • c, err := ln.Accept() • if err != nil { • log.Fatal(err) • } • go handleApi(c) • } • }()

  25. Бизнес логика • type Message struct { • From string • Text string • } • type Client interface { • Send(m Message) • } • var ( • clients = make(map[Client]bool) • clientsMutex sync.Mutex • )

  26. Бизнес логика (2) • func registerClient(c Client) { • clientsMutex.Lock() • clients[c] = true • clientsMutex.Unlock() • } • func unregisterClient(c Client) { • clientsMutex.Lock() • delete(clients, c) • clientsMutex.Unlock() • }

  27. Бизнес логика (3) • func broadcastMessage(m Message) { • clientsMutex.Lock() • for c := range clients { • c.Send(m) • } • clientsMutex.Unlock() • }

  28. HTML шаблоны • var chatPageTempl = template.Must(template.New("").Parse(` • <html> • <body> • <b>Hi, {{.Name}}!</b> • <form> • <input type="text" id="chattext"></input> • <input type="button" value="Say" • onclick="sendMessage()"></input> • </form> • <textarea readonly=1 rows=20 id="alltext"></textarea> • </body> • </html> • `))

  29. HTTP обработчики • func handleChat(w http.ResponseWriter, r *http.Request) { • name := r.FormValue("name") • log.Printf("serving chat page for '%v'", name) • type Params struct { • Name string • } • chatPageTempl.Execute(w, &Params{name}) • }

  30. Websocket обработчик • type WSClient struct { • conn *websocket.Conn • enc *json.Encoder • } • func (c *WSClient) Send(m Message) { • c.enc.Encode(m) • }

  31. Websocket обработчик (2) • func handleWebsocket(ws *websocket.Conn) { • c := &WSClient{ws, json.NewEncoder(ws)} • registerClient(c) • dec := json.NewDecoder(ws) • for { • var m Message • if err := dec.Decode(&m); err != nil { • log.Printf("error reading from websocket: %v", err) • break • } • broadcastMessage(m) • } • unregisterClient(c) • }

  32. Демо

  33. Инструментарий

  34. Сборка Нулевая конфигурация, нет MAKEFILE $ go run myprog.go $ go build myprog $ go get code.google.com/p/go.new/websocket

  35. Пишем код $ go fmt mysource.go $ go vet - статический анализ кода $ godoc - документация goimports/gocode/oracle: поддержка IDE

  36. Тестируем $ go test $ go test -cover $ go test -race Информативные крэш-репорты

  37. Оптимизируем $ go test -bench $ go test -bench -cpu=1,2,4 $ go test -benchmem $ go test -cpuprofile $ go test -memprofile $ go test -blockprofile

  38. Оптимизируем (2) - Профайлер горутин - Трейсер GC - Трейсер планировщика - Трейсер аллокатора памяти - Статистика аллокатора памяти - Дамп кучи

  39. Мониторинг import "expvar" var ( expMsgRecv = expvar.NewInt("msg_recv") expMsgSend = expvar.NewInt("msg_send") ) func broadcastMessage(m Message) { ... expMsgRecv.Add(1) expMsgSend.Add(int64(len(clients))) }

  40. Что дальше? http://golang.org http://tour.golang.org golang-nuts@ Книги: • An Introduction to Programming in Go • Network Programming with Go • Programming in Go: Creating Applications for the 21st Century

  41. Другие доклады по Go • 16:35 Common: Go: аналитика Рунета в реальном времени • 17:45 Python: Go на Google App Engine - просто, надёжно, быстро и недорого. • 19:30 Python: Juju и MaaS - эффективные инструменты развёртывания масштабных систем на "железе" и в "облаках".

  42. Q&A Спасибо! Дмитрий Вьюков, dvyukov@ http://golang.org

More Related