Golang හි වෙබ් සේවාදායක සංවර්ධනය - සරල සිට සංකීර්ණ දක්වා

Golang හි වෙබ් සේවාදායක සංවර්ධනය - සරල සිට සංකීර්ණ දක්වා

අවුරුදු පහකට කලින් මම පටන් ගත්තා ගොෆිෂ් සංවර්ධනය කරන්න, මෙය Golang ඉගෙන ගැනීමට අවස්ථාවක් ලබා දුන්නේය. Go යනු බොහෝ පුස්තකාලවලින් අනුපූරක වූ බලවත් භාෂාවක් බව මට වැටහුණි. Go බහුකාර්ය වේ: විශේෂයෙන්, එය කිසිදු ගැටළුවක් නොමැතිව සේවාදායක පැත්තේ යෙදුම් සංවර්ධනය කිරීමට භාවිතා කළ හැක.

මෙම ලිපිය Go හි සේවාදායකයක් ලිවීම ගැන ය. "Hello world!" වැනි සරල දේවල් වලින් ආරම්භ කර පහත හැකියාවන් සහිත යෙදුමකින් අවසන් කරමු:

- HTTPS සඳහා අපි සංකේතනය කරමු.
- API රවුටරයක් ​​ලෙස වැඩ කිරීම.
- මිඩ්ල්වෙයාර් සමඟ වැඩ කිරීම.
- ස්ථිතික ගොනු සැකසීම.
- නිවැරදි වසා දැමීම.

Skillbox නිර්දේශ කරයි: ප්රායෝගික පාඨමාලාව "පයිතන් සංවර්ධකයා මුල සිටම".

අපි ඔබට මතක් කරමු: "Habr" හි සියලුම පාඨකයින් සඳහා - "Habr" ප්‍රවර්ධන කේතය භාවිතයෙන් ඕනෑම Skillbox පාඨමාලාවකට ලියාපදිංචි වන විට රූබල් 10 ක වට්ටමක්.

හෙලෝ වර්ල්ඩ්!

Go වලදී ඔබට ඉතා ඉක්මනින් වෙබ් සේවාදායකයක් සාදාගත හැක. ඉහත පොරොන්දු වූ “Hello, world!” නැවත ලබා දෙන හසුරුව භාවිතා කිරීමේ උදාහරණයක් මෙන්න.

package main
 
import (
"fmt"
"net/http"
)
 
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
})
http.ListenAndServe(":80", nil)
}

මෙයින් පසු, ඔබ යෙදුම ධාවනය කර පිටුව විවෘත කළහොත් දේශීයව, එවිට ඔබ වහාම "ආයුබෝවන්, ලෝකය!" යන පාඨය දකිනු ඇත. (සියල්ල නිවැරදිව ක්රියා කරන්නේ නම්, ඇත්ත වශයෙන්ම).

අපි පසුව කිහිප වතාවක් හසුරුව භාවිතා කරන්නෙමු, නමුත් පළමුව අපි සියල්ල ක්‍රියා කරන ආකාරය තේරුම් ගනිමු.

net/http

උදාහරණය පැකේජය භාවිතා කළේය net/http, එය සේවාදායකයන් සහ HTTP සේවාලාභීන් යන දෙකම සංවර්ධනය කිරීම සඳහා Go හි මූලික මෙවලම වේ. කේතය තේරුම් ගැනීමට, වැදගත් මූලද්‍රව්‍ය තුනක තේරුම තේරුම් ගනිමු: http.Handler, http.ServeMux සහ http.Server.

HTTP හසුරුවන්න

අපට ඉල්ලීමක් ලැබුණු විට, හසුරුවන්නා එය විශ්ලේෂණය කර ප්‍රතිචාරයක් ජනනය කරයි. Go හි හැසිරවීම් පහත පරිදි ක්‍රියාත්මක වේ:

type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
}

පළමු උදාහරණය http.HandleFunc උපකාරක ශ්‍රිතය භාවිතා කරයි. එය වෙනත් කාර්යයක් ආවරණය කරයි, එය http.ResponseWriter සහ http.Request ServeHTTP වෙත ගෙන යයි.

වෙනත් වචන වලින් කිවහොත්, Golang හි හසුරුවන්නන් තනි අතුරු මුහුණතක් තුළ ඉදිරිපත් කර ඇති අතර, එය ක්රමලේඛකයාට බොහෝ විකල්ප ලබා දෙයි. උදාහරණයක් ලෙස, මිඩ්ල්වෙයාර් ක්‍රියාත්මක කරනු ලබන්නේ හසුරුවන්නක් භාවිතා කරමිනි, එහිදී ServeHTTP පළමුව යමක් කර පසුව වෙනත් හසුරුවන්නෙකුගේ ServeHTTP ක්‍රමය අමතයි.

ඉහත සඳහන් කළ පරිදි, හසුරුවන්නන් ඉල්ලීම් සඳහා ප්‍රතිචාර ජනනය කරයි. නමුත් නිශ්චිත වේලාවක භාවිතා කළ යුත්තේ කුමන විශේෂිත හසුරුවන්නද?

මාර්ගගත කිරීම ඉල්ලන්න

නිවැරදි තේරීමක් කිරීමට, HTTP මල්ටිප්ලෙක්සර් භාවිතා කරන්න. පුස්තකාල ගණනාවක එය muxer හෝ router ලෙස හැඳින්වේ, නමුත් ඒවා සියල්ලම එකම දෙයකි. මල්ටිප්ලෙක්සර් හි කාර්යය වන්නේ ඉල්ලීම් මාර්ගය විශ්ලේෂණය කර සුදුසු හසුරුවන්නා තෝරා ගැනීමයි.

ඔබට සංකීර්ණ මාර්ගගත කිරීම සඳහා සහාය අවශ්‍ය නම්, තෙවන පාර්ශවීය පුස්තකාල භාවිතා කිරීම වඩා හොඳය. වඩාත්ම දියුණු සමහරක් - gorilla/mux и go-chi/chi, මෙම පුස්තකාල කිසිදු ගැටළුවක් නොමැතිව අතරමැදි සැකසුම් ක්රියාත්මක කිරීමට හැකි වේ. ඔවුන්ගේ උපකාරයෙන්, ඔබට Wildcard routing වින්‍යාසගත කළ හැකි අතර වෙනත් කාර්යයන් ගණනාවක් සිදු කළ හැක. ඔවුන්ගේ වාසිය වන්නේ සම්මත HTTP හසුරුවන්න සමඟ අනුකූල වීමයි. ප්රතිඵලයක් වශයෙන්, ඔබට අනාගතයේදී වෙනස් කළ හැකි සරල කේතයක් ලිවිය හැකිය.

සාමාන්ය තත්වයක් තුළ සංකීර්ණ රාමු සමඟ වැඩ කිරීම සඳහා සම්මත නොවන විසඳුම් අවශ්ය වනු ඇති අතර, මෙය පෙරනිමි හසුරුවන්නන්ගේ භාවිතය සැලකිය යුතු ලෙස සංකීර්ණ කරයි. යෙදුම් අතිමහත් බහුතරයක් නිර්මාණය කිරීම සඳහා, පෙරනිමි පුස්තකාලය සහ සරල රවුටරයක එකතුවක් ප්රමාණවත් වනු ඇත.

විමසුම් සැකසීම

ඊට අමතරව, අපට ලැබෙන සම්බන්ධතා සඳහා "සවන් දීම" සහ සියලු ඉල්ලීම් නිවැරදි හසුරුවන්න වෙත හරවා යවන සංරචකයක් අවශ්ය වේ. http.Server හට මෙම කාර්යය පහසුවෙන් හැසිරවිය හැක.

පහත දැක්වෙන්නේ සම්බන්ධතා සැකසීමට අදාළ සියලුම කාර්යයන් සඳහා සේවාදායකය වගකිව යුතු බවයි. උදාහරණයක් ලෙස මෙය TLS ප්‍රොටෝකෝලය භාවිතයෙන් ක්‍රියා කරයි. http.ListenAndServer ඇමතුම ක්‍රියාත්මක කිරීමට, සම්මත HTTP සේවාදායකයක් භාවිතා කරයි.

දැන් අපි වඩාත් සංකීර්ණ උදාහරණ දෙස බලමු.

අපි සංකේතනය කරමු එකතු කිරීම

පෙරනිමියෙන්, අපගේ යෙදුම HTTP ප්‍රොටෝකෝලය හරහා ක්‍රියා කරයි, නමුත් HTTPS ප්‍රොටෝකෝලය භාවිතා කිරීම නිර්දේශ කෙරේ. මේක Go වල අවුලක් නැතුව කරන්න පුලුවන්. ඔබට සහතිකයක් සහ පුද්ගලික යතුරක් ලැබී ඇත්නම්, නිවැරදි සහතිකය සහ යතුරු ගොනු සමඟ ListenAndServeTLS ලියාපදිංචි කිරීම ප්‍රමාණවත් වේ.

http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

ඔබට සෑම විටම වඩා හොඳින් කළ හැකිය.

අපි ගුප්තකේතනය කරමු ස්වයංක්‍රීය අලුත් කිරීම් සමඟ නොමිලේ සහතික ලබා දෙයි. සේවාව භාවිතා කිරීම සඳහා, ඔබට පැකේජයක් අවශ්ය වේ autocert.

එය වින්‍යාස කිරීමට ඇති පහසුම ක්‍රමය නම් http.Serve සමඟ ඒකාබද්ධව autocert.NewListener ක්‍රමය භාවිතා කිරීමයි. HTTP සේවාදායකය ඉල්ලීම් සකසන අතරතුර TLS සහතික ලබා ගැනීමට සහ යාවත්කාලීන කිරීමට ක්‍රමය ඔබට ඉඩ සලසයි:

http.Serve(autocert.NewListener("example.com"), nil)

අපි බ්‍රව්සරයේ විවෘත කළහොත් උදාහරණයක් ලෙස, අපට HTTPS ප්‍රතිචාරයක් ලැබෙනු ඇත “ආයුබෝවන්, ලෝකය!”

ඔබට වඩාත් සවිස්තරාත්මක වින්‍යාසයක් අවශ්‍ය නම්, ඔබ autocert.Manager කළමනාකරු භාවිතා කළ යුතුය. ඉන්පසුව අපි අපේම http.Server උදාහරණයක් සාදා (මෙතෙක් අපි එය පෙරනිමියෙන් භාවිතා කළෙමු) සහ කළමනාකරු TLSConfig සේවාදායකයට එක් කරන්න:

m := &autocert.Manager{
Cache:      autocert.DirCache("golang-autocert"),
Prompt:     autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"),
}
server := &http.Server{
    Addr:      ":443",
    TLSConfig: m.TLSConfig(),
}
server.ListenAndServeTLS("", "")

මෙය ස්වයංක්‍රීය සහතික අලුත් කිරීම සමඟ පූර්ණ HTTPS සහාය ක්‍රියාත්මක කිරීමට පහසු ක්‍රමයකි.

අභිරුචි මාර්ග එකතු කිරීම

සම්මත පුස්තකාලයේ ඇතුළත් පෙරනිමි රවුටරය හොඳයි, නමුත් එය ඉතා මූලික වේ. බොහෝ යෙදුම් සඳහා කැදැලි සහ වයිල්ඩ්කාඩ් මාර්ග ඇතුළුව වඩාත් සංකීර්ණ මාර්ගගත කිරීම් හෝ මාර්ග රටා සහ පරාමිතීන් සැකසීමේ ක්‍රියා පටිපාටියක් අවශ්‍ය වේ.

මෙම අවස්ථාවේදී පැකේජ භාවිතා කිරීම වටී gorilla/mux и go-chi/chi. දෙවැන්න සමඟ වැඩ කරන්නේ කෙසේදැයි අපි ඉගෙන ගනිමු - උදාහරණයක් පහත දැක්වේ.

අපගේ API සඳහා මාර්ග අඩංගු api/v1/api.go ගොනුව ලබා දී ඇත:

/ HelloResponse is the JSON representation for a customized message
type HelloResponse struct {
Message string `json:"message"`
}
 
// HelloName returns a personalized JSON message
func HelloName(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
response := HelloResponse{
Message: fmt.Sprintf("Hello %s!", name),
}
jsonResponse(w, response, http.StatusOK)
}
 
// NewRouter returns an HTTP handler that implements the routes for the API
func NewRouter() http.Handler {
r := chi.NewRouter()
r.Get("/{name}", HelloName)
return r
}

අපි ප්රධාන ගොනුවේ මාර්ග සඳහා api/vq උපසර්ගය සකස් කරමු.

පසුව අපට මෙය අපගේ ප්‍රධාන යෙදුමේ ඇති api/v1/ උපසර්ගය යටතේ අපගේ ප්‍රධාන රවුටරයට සවි කළ හැක:

// NewRouter returns a new HTTP handler that implements the main server routes
func NewRouter() http.Handler {
router := chi.NewRouter()
    router.Mount("/api/v1/", v1.NewRouter())
    return router
}
http.Serve(autocert.NewListener("example.com"), NewRouter())

Go හි සංකීර්ණ මාර්ග සමඟ වැඩ කිරීමේ පහසුව විශාල, සංකීර්ණ යෙදුම්වල ව්‍යුහගත කිරීම සහ නඩත්තු කිරීම සරල කිරීමට හැකි වේ.

මිඩ්ල්වෙයාර් සමඟ වැඩ කිරීම

වේදිකාගත කිරීම යනු එක් HTTP හසුරුවන්නක් තවත් එකකින් ඔතා, සත්‍යාපනය, සම්පීඩනය, ලොග් කිරීම සහ තවත් කාර්යයන් කිහිපයක් ඉක්මනින් සිදු කිරීමට හැකි වේ.

උදාහරණයක් ලෙස, අපි http.Handler අතුරුමුහුණත දෙස බලමු; සේවා භාවිතා කරන්නන් සත්‍යාපනය කරන හසුරුවක් ලිවීමට අපි එය භාවිතා කරමු.

func RequireAuthentication(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !isAuthenticated(r) {
            http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
            return
        }
        // Assuming authentication passed, run the original handler
        next.ServeHTTP(w, r)
    })
}

චි වැනි තෙවන පාර්ශවීය රවුටර ඇත, එය ඔබට මිඩ්ල්වෙයාර් ක්‍රියාකාරීත්වය දීර්ඝ කිරීමට ඉඩ සලසයි.

ස්ථිතික ගොනු සමඟ වැඩ කිරීම

Go සම්මත පුස්තකාලයට රූප, ජාවාස්ක්‍රිප්ට් සහ CSS ගොනු ඇතුළු ස්ථිතික අන්තර්ගතයන් සමඟ වැඩ කිරීමේ හැකියාවන් ඇතුළත් වේ. http.FileServer ශ්‍රිතය හරහා ඒවාට ප්‍රවේශ විය හැක. එය නිශ්චිත නාමාවලියකින් ගොනු සපයන හසුරුවන්නක් ආපසු ලබා දෙයි.

func NewRouter() http.Handler {
    router := chi.NewRouter()
    r.Get("/{name}", HelloName)
 
// Настройка раздачи статических файлов
staticPath, _ := filepath.Abs("../../static/")
fs := http.FileServer(http.Dir(staticPath))
    router.Handle("/*", fs)
    
    return r

http.Dir ප්‍රධාන index.html ගොනුව නොමැති නම් ඩිරෙක්ටරියේ අන්තර්ගතය ප්‍රදර්ශනය කරන බව මතක තබා ගැනීම වටී. මෙම අවස්ථාවේදී, බහලුම අවදානමට ලක්වීම වැළැක්වීම සඳහා, ඔබ පැකේජය භාවිතා කළ යුතුය unindexed.

නිවැරදි වසා දැමීම

Go හි HTTP සේවාදායකයේ graceful shutdown නමින් විශේෂාංගයක් ද ඇත. මෙය Shutdown() ක්‍රමය භාවිතයෙන් කළ හැක. සේවාදායකය goroutine එකකින් ආරම්භ කර ඇති අතර, පසුව බාධා සංඥාවක් ලැබීමට නාලිකාවට සවන් දෙනු ලැබේ. සංඥාව ලැබුණු වහාම, සේවාදායකය අක්රිය වේ, නමුත් වහාම නොවේ, නමුත් තත්පර කිහිපයකින් පසුව.

handler := server.NewRouter()
srv := &http.Server{
    Handler: handler,
}
 
go func() {
srv.Serve(autocert.NewListener(domains...))
}()
 
// Wait for an interrupt
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
 
// Attempt a graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(ctx)

නිගමනය ලෙස

Go යනු විශ්වීය සම්මත පුස්තකාලයක් සහිත බලවත් භාෂාවකි. එහි පෙරනිමි හැකියාවන් ඉතා පුළුල් වන අතර ඒවා අතුරුමුහුණත් භාවිතයෙන් වැඩි දියුණු කළ හැකිය - මෙය ඔබට සැබවින්ම විශ්වාසදායක HTTP සේවාදායකයන් සංවර්ධනය කිරීමට ඉඩ සලසයි.

Skillbox නිර්දේශ කරයි:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න