GoDasturchi
HTTP Service Communication

HTTP Service Communication

HTTP orqali servislar aloqasi

Ikki qo'shni davlat bir-biri bilan gaplashish uchun elchilar yuboradi, umumiy tilda muzokara qiladi. Mikroservislar ham xuddi shunday: ular bitta dastur ichida emas, ALOHIDA jarayonlarda (ko'pincha alohida serverlarda) ishlaydi, shuning uchun bir-biri bilan oddiy funksiya chaqiruvi orqali emas, balki tarmoq (odatda HTTP) orqali "gaplashadi".

example.go
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
)

// UserService'ni chaqirganda nima qaytarishini simulyatsiya qilamiz
// (haqiqiy loyihada bu — alohida serverga HTTP so'rovi bo'lardi)
type userLookupTransport struct{}

func (t *userLookupTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(bytes.NewBufferString(`{"id":"u1","name":"Aziz"}`)),
		Header:     make(http.Header),
	}, nil
}

// OrderService — UserService'ga HTTP orqali murojaat qiladi
func makeOrderHandler(client *http.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		resp, err := client.Get("http://user-service.internal/users/u1")
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		defer resp.Body.Close()
		body, _ := io.ReadAll(resp.Body)
		fmt.Fprintf(w, "buyurtma yaratildi, foydalanuvchi: %s", string(body))
	}
}

func main() {
	client := &http.Client{Transport: &userLookupTransport{}}
	orderHandler := makeOrderHandler(client)

	req := httptest.NewRequest("POST", "/orders", nil)
	rec := httptest.NewRecorder()
	orderHandler(rec, req)
	fmt.Println(rec.Body.String())
}

Bu misolda ikkita "servis" o'rtasidagi haqiqiy aloqani ko'ramiz: makeOrderHandler (OrderService'ning handleri) client.Get("http://user-service.internal/...") orqali UserService'ga "murojaat qiladi". Haqiqiy production'da bu URL — UserService'ning haqiqiy tarmoq manzili bo'lardi. Bizning o'quv muhitimizda esa userLookupTransport UserService'ning ROLINI o'ynaydi ("HTTP Client Basics" darsida ko'rgan RoundTripper texnikasi) — bu bizga haqiqiy ikkita server ishga tushirmasdan, ularning ORASIDAGI ALOQA mantig'ini o'rganish imkonini beradi.

E'tibor bering: makeOrderHandler client *http.Clientni PARAMETR sifatida oladi ("Dependency Injection" darsida ko'rgan naqsh) — bu OrderService'ning o'zi qaysi HTTP klient bilan ishlashini "bilmasligi", faqat unga BERILGAN klientdan foydalanishini ta'minlaydi. Bu — production'da haqiqiy tarmoqqa ulanadigan klient, testda esa RoundTripper bilan sun'iy javob beradigan klient berish imkonini beradi.

>_ Exercise

InventoryService'ga murojaat qiluvchi handler yozing.

  • inventoryTransport yozing: RoundTrip {"in_stock":true} JSON'ini qaytarsin
  • makeCheckoutHandler(client) yozing: client.Get("http://inventory-service.internal/check") qilib, javobni "ombor holati: <javob>" formatida chop etsin
  • httptest bilan chaqirib, natijani chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Mikroservislar bir-biri bilan HTTP orqali "gaplashadi"; klientni parametr sifatida berish (dependency injection) servislarni haqiqiy tarmoqsiz, ishonchli tarzda sinash imkonini beradi.

NEXT UP

Service Discovery Patterns

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

HTTP Service Communication

HTTP orqali servislar aloqasi

Ikki qo'shni davlat bir-biri bilan gaplashish uchun elchilar yuboradi, umumiy tilda muzokara qiladi. Mikroservislar ham xuddi shunday: ular bitta dastur ichida emas, ALOHIDA jarayonlarda (ko'pincha alohida serverlarda) ishlaydi, shuning uchun bir-biri bilan oddiy funksiya chaqiruvi orqali emas, balki tarmoq (odatda HTTP) orqali "gaplashadi".

example.go
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
)

// UserService'ni chaqirganda nima qaytarishini simulyatsiya qilamiz
// (haqiqiy loyihada bu — alohida serverga HTTP so'rovi bo'lardi)
type userLookupTransport struct{}

func (t *userLookupTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(bytes.NewBufferString(`{"id":"u1","name":"Aziz"}`)),
		Header:     make(http.Header),
	}, nil
}

// OrderService — UserService'ga HTTP orqali murojaat qiladi
func makeOrderHandler(client *http.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		resp, err := client.Get("http://user-service.internal/users/u1")
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		defer resp.Body.Close()
		body, _ := io.ReadAll(resp.Body)
		fmt.Fprintf(w, "buyurtma yaratildi, foydalanuvchi: %s", string(body))
	}
}

func main() {
	client := &http.Client{Transport: &userLookupTransport{}}
	orderHandler := makeOrderHandler(client)

	req := httptest.NewRequest("POST", "/orders", nil)
	rec := httptest.NewRecorder()
	orderHandler(rec, req)
	fmt.Println(rec.Body.String())
}

Bu misolda ikkita "servis" o'rtasidagi haqiqiy aloqani ko'ramiz: makeOrderHandler (OrderService'ning handleri) client.Get("http://user-service.internal/...") orqali UserService'ga "murojaat qiladi". Haqiqiy production'da bu URL — UserService'ning haqiqiy tarmoq manzili bo'lardi. Bizning o'quv muhitimizda esa userLookupTransport UserService'ning ROLINI o'ynaydi ("HTTP Client Basics" darsida ko'rgan RoundTripper texnikasi) — bu bizga haqiqiy ikkita server ishga tushirmasdan, ularning ORASIDAGI ALOQA mantig'ini o'rganish imkonini beradi.

E'tibor bering: makeOrderHandler client *http.Clientni PARAMETR sifatida oladi ("Dependency Injection" darsida ko'rgan naqsh) — bu OrderService'ning o'zi qaysi HTTP klient bilan ishlashini "bilmasligi", faqat unga BERILGAN klientdan foydalanishini ta'minlaydi. Bu — production'da haqiqiy tarmoqqa ulanadigan klient, testda esa RoundTripper bilan sun'iy javob beradigan klient berish imkonini beradi.

>_ Exercise

InventoryService'ga murojaat qiluvchi handler yozing.

  • inventoryTransport yozing: RoundTrip {"in_stock":true} JSON'ini qaytarsin
  • makeCheckoutHandler(client) yozing: client.Get("http://inventory-service.internal/check") qilib, javobni "ombor holati: <javob>" formatida chop etsin
  • httptest bilan chaqirib, natijani chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Mikroservislar bir-biri bilan HTTP orqali "gaplashadi"; klientni parametr sifatida berish (dependency injection) servislarni haqiqiy tarmoqsiz, ishonchli tarzda sinash imkonini beradi.

NEXT UP

Service Discovery Patterns