一、目标二、使用步骤1、安装consul,我们可以直接使用官方提供的二进制文件进行安装部署。官网地址为https://www.consul.io/downloads。下载后成为可执行文件。实验过程中可以直接使用consulagent-dev命令启动单节点consul。在启动打印日志中可以看到agent:StartedHTTPserveron127.0.0.1:8500(tcp),我们可以在浏览器中直接访问127.0.0.1:8500可以看到如下内容。到这里,我们的consul已经成功启动了。2、服务注册在网络编程中,一般都会提供项目的IP、PORT、PROTOCOL。在服务管理中,我们还需要知道对应的服务Name,实例名,以及一些自定义的扩展信息这里使用ServiceInstance接口指定一些注册服务需要的信息,使用DefaultServiceInstance实现typeServiceInstance接口{//returnTheuniqueinstanceIDasregistered.GetInstanceId()string//返回注册的服务ID.GetServiceId()string//返回注册服务实例的主机名.GetHost()string//返回注册服务实例的端口.GetPort()int//返回注册服务实例的端口是否使用HTTPS.IsSecure()bool//返回服务实例关联的key/value对元数据.GetMetadata()map[string]Servicestruct}typeDefault{InstanceIdstringServiceIdstringHoststringPortintSecureboolMetadatamap[string]string}funcNewDefaultServiceInstance(serviceIdstring,hoststring,portint,securebool,metadatamap[string]string,instanceIdstring)(*DefaultServiceInstance,error){//如果没有传入IP则获取一下,这个方法在多网卡的情况下,并不好用iflen(host)==0{localIP,err:=util.GetLocalIP()iferr!=nil{returnil,err}host=localIP}iflen(instanceId)==0{instanceId=serviceId+"-"+strconv.FormatInt(time.Now().Unix(),10)+"-"+strconv.Itoa(rand.Intn(9000)+1000)}return&DefaultServiceInstance{InstanceId:instanceId,ServiceId:serviceId,Host:host,Port:端口,安全:安全,元数据:元数据},nil}func(serviceInstanceDefaultServiceInstance)GetInstanceId()字符串{returnserviceInstance.InstanceId}func(serviceInstanceDefaultServiceInstance)GetServiceId()字符串{returnserviceInstance.ServiceId}func(serviceInstanceDefaultServiceInstance)GetHost()字符串{returnserviceInstance。主机}func(serviceInstanceDefaultServiceInstance)GetPort()int{returnserviceInstance.Port}func(serviceInstanceDefaultServiceInstance)IsSecure()bool{returnserviceInstance.Secure}func(serviceInstanceDefaultServiceInstance)GetMetadata()map[string]string{returnserviceInstance.Metadata}定义接口指定了需要注册的服务的必要信息。下面定义了服务注册和移除的方法typeServiceRegistryinterface{Register(serviceInstancecloud.ServiceInstance)boolDeregister()}具体实现因为consul提供了http接口来操作consul,我们也可以使用http请求方法来进行注册和移除操作,见https:///万维网。consul.io/api-docs,consul默认提供了go语言的实现,这里直接使用github.com/hashicorp/consul/apiimport("errors""fmt""github.com/hashicorp/consul/api""strconv""unsafe")typeconsulServiceRegistrystruct{serviceInstancesmap[string]map[string]cloud.ServiceInstanceclientapi.ClientlocalServiceInstancecloud.ServiceInstance}func(cconsulServiceRegistry)Register(serviceInstancecloud.ServiceInstance)bool{//创建服务注册到consultoregistration:=new(api.AgentServiceRegistration)registration.ID=serviceInstance.GetInstanceId()registration.Name=serviceInstance.GetServiceId()registration.Port=serviceInstance.GetPort()vartags[]stringifserviceInstance.IsSecure(){tags=append(tags,"secure=true")}else{tags=append(tags,"secure=false")}ifserviceInstance。GetMetadata()!=nil{vartags[]stringforkey,value:=rangeserviceInstance.GetMetadata(){tags=append(tags,key+"="+value)}registration.Tags=tags}registration.Tags=tagsregistration.Address=serviceInstance.GetHost()//添加consul健康检查回调函数check:=new(api.AgentServiceCheck)schema:="http"ifserviceInstance.IsSecure(){schema="https"}check.HTTP=fmt.Sprintf("%s://%s:%d/actuator/health",schema,registration.Address,registration.Port)check.Timeout="5s"check.Interval="5s"check.DeregisterCriticalServiceAfter="20s"//故障检查失败30s后consul会自动删除注册服务registration.check=check//注册服务到consulerr:=c.client.Agent().ServiceRegister(registration)iferr!=nil{fmt.Println(err)returnfalse}ifc.serviceInstances==nil{c.服务实例=map[string]map[string]cloud.ServiceInstance{}}services:=c.serviceInstances[serviceInstance.GetServiceId()]ifservices==nil{services=map[string]cloud.ServiceInstance{}}services[serviceInstance.GetInstanceId()]=serviceInstancec.serviceInstances[serviceInstance.GetServiceId()]=servicesc.localServiceInstance=serviceInstancereturntrue}//deregisteraservicefunc(cconsulServiceRegistry)Deregister(){ifc.serviceInstances==nil{return}services:=c.serviceInstances[c.localServiceInstance.GetServiceId()]ifservices==nil{return}delete(services,c.localServiceInstance.GetInstanceId())iflen(services)==0{delete(c.serviceInstances,c.localServiceInstance.GetServiceId())}_=c.client.Agent().ServiceDeregister(c.localServiceInstance.GetInstanceId())c.localServiceInstance=nil}//newaconsulServiceRegistryinstance//tokenisoptionalfuncNewConsulServiceRegistry(hoststring,portint,tokenstring)(*consulServiceRegistry,error){iflen(host)<3{returnnil,errors.New("checkhost")}我fport<=0||port>65535{returnnil,errors.New("checkport,portshouldbetween1and65535")}config:=api.DefaultConfig()config.Address=host+":"+strconv.Itoa(port)config.Token=tokenclient,err:=api.NewClient(config)iferr!=nil{returnil,err}return&consulServiceRegistry{client:*client},nil}测试用例注册服务的代码基本完成,我们来测试一下funcTestConsulServiceRegistry(t*testing.T){host:="127.0.0.1"port:=8500registryDiscoveryClient,_:=extension.NewConsulServiceRegistry(host,port,"")ip,err:=util.GetLocalIP()iferr!=nil{t.Error(err)}serviceInstanceInfo,_:=cloud.NewDefaultServiceInstance("go-user-server","",8090,false,map[string]string{"user":"zyn"},"")registryDiscoveryClient.Register(serviceInstanceInfo)r:=gin.Default()//健康检测接口,其实只要是200就认为成功r.GET("/actuator/health",func(c*gin.Context){c.JSON(200,gin.H{"message":"pong",})})err=r.Run(":8090")iferr!=nil{registryDiscoveryClient.Deregister()}}如果成功,你会在consul中看到go-user-server服务3.服务发现在服务发现中,一般需要两个方法获取所有服务列表和获取指定服务的所有实例信息接口定义typeDiscoveryClientinterface{/***GetsallServiceInstancesassociatedwithaparticularserviceId.*@paramserviceIdTheserviceIdtoquery.*@returnAListofServiceInstance.*/GetInstances(serviceIdstring)([]cloud.ServiceInstance,error)/***@returnAllknownserviceIDs.*/GetServices()([]string,error)}具体实现实现typeconsulServiceRegistrystruct{serviceInstancesmap[string]map[string]cloud.ServiceInstanceclientapi.ClientlocalServiceInstancecloud.ServiceInstance}func(cconsulServiceRegistry)GetInstances(serviceIdstring)([]cloud.ServiceInstance,error){catalogService,_,_:=c.client.Catalog().Service(serviceId,"",nil)iflen(catalogService)>0{result:=make([]cloud.ServiceInstance,len(catalogService))forind例如,服务器:=rangecatalogService{s:=cloud.DefaultServiceInstance{InstanceId:sever.ServiceID,ServiceId:sever.ServiceName,Host:sever.Address,Port:sever.ServicePort,元数据:sever.ServiceMeta,}result[index]=s}returnresult,nil}returnnil,nil}func(cconsulServiceRegistry)GetServices()([]string,error){services,_,_:=c.client.Catalog().Services(nil)result:=make([]string,unsafe.Sizeof(services))index:=0forserviceName,_:=rangeservices{result[index]=serviceNameindex++}returnresult,nil}//newaconsulServiceRegistryinstance//tokenisoptionalfuncNewConsulServiceRegistry(hoststring,portint,tokenstring)(*consulServiceRegistry,error){iflen(host)<3{returnil,errors.New("checkhost")}ifport<=0||port>65535{returnnil,errors.New("checkport,portshouldbetween1and65535")}config:=api.DefaultConfig()config.Address=host+":"+strconv.Itoa(port)config.Token=tokenclient,err:=api.NewClient(config)iferr!=nil{returnil,err}return&consulServiceRegistry{client:*client},nil}测试用例funcTestConsulServiceDiscovery(t*testing.T){host:="127.0.0.1"port:=8500token:=""registryDiscoveryClient,错误:=extension.NewConsulServiceRegistry(host,port,token)iferr!=nil{panic(err)}t.Log(registryDiscoveryClient.GetServices())t.Log(registryDiscoveryClient.GetInstances("go-user-server"))}结果consul_service_registry_test.go:57:[consulgo-user-server]
