简单分布式系统开发day02

简单分布式系统开发day02,第1张

源码已经上传,有需要可在资源下载。在分布式day01的基础上,本节的新增内容主要是注册服务并独立运行,

首先在distributed文件夹下创建registry文件夹并在其下分别创建client.go,registration.go和server.go文件。
1、client.go

package registry

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

func RegisterService(r Registration)error  {
	buf := new(bytes.Buffer)
	enc := json.NewEncoder(buf)
	err :=enc.Encode(r)
	if err!=nil{
		return err
	}
	res,err := http.Post(ServiceURL,"application/json",buf)
    if err !=nil{
		return err
	}
	if res.StatusCode!=http.StatusOK{
		return fmt.Errorf("Failed to register")
	}
	return nil
}

主要用于客户端的注册服务,其中创建Post请求向注册地址即ServiceURL请求注册服务
2、registration.go

package registry
type  Registration struct {
	ServiceName ServiceName
	ServiceURL string
}
type ServiceName string
const(
	LogService = ServiceName("LogService")
)

创建注册信息结构体包括服务名服务地址
3、server.go

package registry

import (
	"encoding/json"
	"log"
	"net/http"
	"sync"
)

const  ServerPort =":3000"
const ServiceURL = "http://localhost"+ServerPort+"/services"
type registry struct {
	registrations []Registration//已经注册的服务
	mutex *sync.Mutex//因为集合动态变化且可能并发访问为保证线程安全则加互斥锁
}

func (r *registry)add(reg Registration)error  {
      r.mutex.Lock()
	  r.registrations = append(r.registrations,reg)
	  r.mutex.Unlock()
	  return  nil
}

//注册的服务集群
var reg = registry{
	registrations: make([]Registration,0),
	mutex: new(sync.Mutex),
}

type  RegistryService struct {}//让其成为一个Handle

func (s RegistryService)ServeHTTP(w http.ResponseWriter,r *http.Request)  {
   log.Println("Request received")
	switch r.Method {
	case http.MethodPost:
		dec := json.NewDecoder(r.Body)
		var r Registration
		err := dec.Decode(&r)
		if err!=nil{
			log.Println(err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		log.Printf("Add service:%v with URL %v\n",r.ServiceName,r.ServiceURL)
		err = reg.add(r)
		if err!=nil{
			log.Println(err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}
	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

用于将请求注册的服务加入注册服务集群中,此时的RegistryService因为实现了ServeHTTP接口,故成为了一个Handle,当请求为 //访问该地址后,启动RegistryService使其成为一个handle,如下,当请求为/services时,RegistryService便会将服务信息添加到注册集群中

http.Handle("/services",&registry.RegistryService{})

在cmd包下创建如下目录

main.go的内容如下

package main
import (
	"context"
	"distributed/registry"
	"fmt"
	"log"
	"net/http"
)
//注册服务
func main() {
	//访问该地址后,启动RegistryService使其称为一个handle
	http.Handle("/services",&registry.RegistryService{})
	//创建上下文和取消上下文
	ctx,cancle :=context.WithCancel(context.Background())
	//创建http.Server变量
	var srv http.Server
	//服务端口
	srv.Addr = registry.ServerPort
	go func() {
		//启动服务是否成功,日志记录
		log.Println(srv.ListenAndServe())
		//结束线程
		cancle()
	}()
	go func(){
		fmt.Println("Registry service started.Press any key to stop.")
		var s string
		fmt.Scanln(&s)
		srv.Shutdown(ctx)
		cancle()
	}()

	<-ctx.Done()
	fmt.Println("shutting down registy service")
}

其中ctx的作用,个人认为是退出服务的条件,即让<-ctx.Done不再阻塞,即可退出。
参数做如下修改


其中先执行注册服务,再执行日志服务

测试工具Postman

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994508.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存