当前位置: 首页 > news >正文

建设流网站项目/中央常委成员名单

建设流网站项目,中央常委成员名单,微信网页制作网站建设,乘客电梯做推广的网站一 服务发现基础概念 为什么需要服务发现 在微服务架构中,在生产环境中服务提供方都是以集群的方式对外提供服务,集群中服务的IP随时都可能发生变化,如服务重启,发布,扩缩容等,因此我们需要及时获取到对应…

一 服务发现基础概念

为什么需要服务发现
在微服务架构中,在生产环境中服务提供方都是以集群的方式对外提供服务,集群中服务的IP随时都可能发生变化,如服务重启,发布,扩缩容等,因此我们需要及时获取到对应的服务节点,这个获取的过程其实就是“服务发现”。

1.1  基础概念

  • 服务的注册(Service Registration)

    当服务启动的时候,应该通过某种形式(比如调用API、产生上线事件消息、在Etcd中记录、存数据库等等)把自己(服务)的信息通知给服务注册中心,这个过程一般是由微服务框架来完成,业务代码无感知。

  • 服务的维护(Service Maintaining)

    尽管在微服务框架中通常都提供下线机制,但并没有办法保证每次服务都能优雅下线(Graceful Shutdown),而不是由于宕机、断网等原因突然失联,所以,在微服务框架中就必须要尽可能的保证维护的服务列表的正确性,以避免访问不可用服务节点的尴尬。

  • 服务的发现(Service Discovery)

    这里所说的发现特指消费者从微服务框架(服务发现模块)中,把一个服务标识(一般是服务名)转换为服务实际位置(一般是ip地址)的过程。这个过程(可能是调用API,监听Etcd,查询数据库等)业务代码无感知。

1.2服务发现的两种模式

服务端服务发现

服务调用方无需关注服务发现的具体细节,只需要知道服务的DNS域名即可。

对基础设施来说,需要专门支持负载均衡器,对于请求链路来说多了一次网络跳转,会有性能损耗。

客户端服务发现

对于客户端服务发现来说,由于客户端和服务端采用了直连的方式,比服务端服务发现少了一次网络跳转,对于服务调用方来说需要内置负载均衡器,不同的语言需要各自实现。

客户端服务发现&服务端服务发现对比

对于微服务架构来说,我们期望的是去中心化依赖,中心化的依赖会让架构变得复杂,当出现问题的时候也会让整个排查链路变得繁琐,所以在 go-zero 中采用的是客户端服务发现的模式。

二 grpc中的服务发现

1.1 grpc客户端发起调用

在介绍Resolver之前先看下grpc官方给出的客户端调用列子。

代码地址:grpc-go/examples/helloworld/greeter_client at master · grpc/grpc-go · GitHub

核心内容分三块:

  • 调用 grpc.Dial 方法,指定服务端 target,创建 grpc 连接代理对象 ClientConn
  • 调用 proto.NewGreeterClient 方法,基于 pb 桩代码构造客户端实例
  • 调用 client.SayHello 方法,真正发起 grpc 请求
package mainimport ("context""flag""log""time""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"pb "google.golang.org/grpc/examples/helloworld/helloworld"
)const (defaultName = "world"
)var (addr = flag.String("addr", "localhost:50051", "the address to connect to")name = flag.String("name", defaultName, "Name to greet")
)func main() {flag.Parse()// Set up a connection to the server.conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()c := pb.NewGreeterClient(conn)// Contact the server and print out its response.ctx, cancel := context.WithTimeout(context.Background(), time.Second)defer cancel()r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})if err != nil {log.Fatalf("could not greet: %v", err)}log.Printf("Greeting: %s", r.GetMessage())
}

最终通过 ClientConn 的Invoke 方法真正发起调用请求。

func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {out := new(HelloReply)err := c.cc.Invoke(ctx, Greeter_SayHello_FullMethodName, in, out, opts...)if err != nil {return nil, err}return out, nil
}


1.2  grpc reslover调用流程

dail创建连接源码入口位于grpc/client.go 中, 我这里先知关注parseTargetAndFindResolver方法

func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {//.......// Determine the resolver to use.if err := cc.parseTargetAndFindResolver(); err != nil {return nil, err}//.......
}

target句法可参考gprc官方文档
// The target name syntax is defined in
https://github.com/grpc/grpc/blob/master/doc/naming.md.

parseTargetAndFindResolver解析用户的拨号目标 并存储在`cc.parsedTarget`中。

要使用的解析器是根据解析的目标中的方案确定的并将其存储在“cc.resolverBuilder”中。 

// parseTargetAndFindResolver parses the user's dial target and stores the
// parsed target in `cc.parsedTarget`.
//
// The resolver to use is determined based on the scheme in the parsed target
// and the same is stored in `cc.resolverBuilder`.
//
// Doesn't grab cc.mu as this method is expected to be called only at Dial time.
func (cc *ClientConn) parseTargetAndFindResolver() error {channelz.Infof(logger, cc.channelzID, "original dial target is: %q", cc.target)var rb resolver.BuilderparsedTarget, err := parseTarget(cc.target)if err != nil {channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", cc.target, err)} else {channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)rb = cc.getResolver(parsedTarget.URL.Scheme)if rb != nil {cc.parsedTarget = parsedTargetcc.resolverBuilder = rbreturn nil}}// We are here because the user's dial target did not contain a scheme or// specified an unregistered scheme. We should fallback to the default// scheme, except when a custom dialer is specified in which case, we should// always use passthrough scheme.defScheme := resolver.GetDefaultScheme()channelz.Infof(logger, cc.channelzID, "fallback to scheme %q", defScheme)canonicalTarget := defScheme + ":///" + cc.targetparsedTarget, err = parseTarget(canonicalTarget)if err != nil {channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", canonicalTarget, err)return err}channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)rb = cc.getResolver(parsedTarget.URL.Scheme)if rb == nil {return fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme)}cc.parsedTarget = parsedTargetcc.resolverBuilder = rbreturn nil
}

阅读完parseTargetAndFindResolver 函数,可以看到会将builder存储到cc.resolverBuilder字段中,返回DialContext函数,发现newCCResolverWrapper会使用cc.resolverBuilder字段。

我们继续阅读newCCResolverWrapper函数源码:
newCCResolverWrapper使用resolver.Builder来构建一个resolver,返回一个ccResolverWrapper对象,该对象包装新构建的解析器。

// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
// returns a ccResolverWrapper object which wraps the newly built resolver.
func newCCResolverWrapper(cc resolverStateUpdater, opts ccResolverWrapperOpts) (*ccResolverWrapper, error) {ctx, cancel := context.WithCancel(context.Background())ccr := &ccResolverWrapper{cc:                  cc,channelzID:          opts.channelzID,ignoreServiceConfig: opts.bOpts.DisableServiceConfig,serializer:          grpcsync.NewCallbackSerializer(ctx),serializerCancel:    cancel,}r, err := opts.builder.Build(opts.target, ccr, opts.bOpts)if err != nil {cancel()return nil, err}ccr.resolver = rreturn ccr, nil
}

 在newCCResolverWrapper 方法 opts.builder.Build(opts.target, ccr, opts.bOpts)调用了我们自定义的Build方法。

三 总结 relover调用时序图:

http://www.jmfq.cn/news/5237749.html

相关文章:

  • 朝阳公司做网站/淘宝指数在线查询
  • 社交网站模板/淄博网络推广公司哪家好
  • 网站开发方案书/seo交流群
  • 承德公司做网站/网络推广100种方法
  • wordpress网站报价/关键词排名优化网站
  • 做建材一般去什么网站宣传/自媒体平台注册官网下载
  • 邯郸市建设局网站2017/整站优化是什么意思
  • 青岛高端网站建设公司/百度搜索引擎官网入口
  • 大连市自然资源局/优化网站快速排名软件
  • 湖南网站建设开发/seo关键词排名优化教程
  • 网站做3儿童车开场动画/软文拟发布的平台与板块
  • 浙江网站建设的要求/神马网站快速排名案例
  • 体育直播网站制作开发/c++线上培训机构哪个好
  • 成都疫情最新新闻/西安seo外包平台
  • 直播间搭建/新乡seo顾问
  • 湛江赤坎海田网站建设招聘/合肥新闻 今天 最新消息
  • WordPress文章内容密码可见/seo服务外包报价
  • 做全世界的生意的网站/seo排名策略
  • 魏县网络营销推广方法/关键词优化精灵
  • 官方网站怎么做/2022年最火的关键词
  • 广州天河网站制作/直通车推广怎么做
  • 特色的岑溪网站开发/百度网盟推广官方网站
  • wordpress搭建学校网站/海东地区谷歌seo网络优化
  • 个人网站建设的要点/企业做推广有几种方式
  • 专业做网站上海/深圳外贸推广公司
  • 成都网站建设哪家专业而且比较便宜/seo搜索引擎优化介绍
  • 本地服务网站开发/日本搜索引擎
  • 苏州集团网站制作开发/百度有专做优化的没
  • 免费b2b网站大全 外贸/做网站排名优化的公司
  • 公司网站建设方案详细/关键词收录查询工具