精华内容
下载资源
问答
  • 在微服务架构或分布式环境下,服务注册与发现技术不可或缺​,这也是程序员进阶之路必须要掌握的核心技术之一,本文通过图解的方式带领大家轻轻松松掌握。 一、引入服务注册与发现组件的原因 先来看一个问题,...

    本文 Github/javamap 已收录,有Java程序员进阶技术知识地图以及我的系列文章,欢迎大家Star。

    在微服务架构或分布式环境下,服务注册与发现技术不可或缺​,这也是程序员进阶之路必须要掌握的核心技术之一,本文通过图解的方式带领大家轻轻松松掌握。

     

    一、引入服务注册与发现组件的原因

    先来看一个问题,假如现在我们要做一个商城项目,作为架构师的你应该怎样设计系统的架构?你心里肯定在想:这还不容易直接照搬淘宝的架构不就行了。但在现实的创业环境中一个项目可能是九死一生,如果一开始投入巨大的人力和财力,一旦项目失败损失就很大。

    作为一位有经验的架构师需要结合公司财力、人力投入预算等现状选择最适合眼下的架构才是王道。大型网站都是从小型网站发展而来,架构也是一样。

    任何一个大型网站的架构都不是从一开始就一层不变的,而是随着用户量和数据量的不断增加不断迭代演进的结果。

    在架构不断迭代演进的过程中我们会遇到很多问题,技术发展的本质就是不断发现问题再解决问题,解决问题又发现问题

     

    单体架构

    在系统建立之初可能不会有特别多的用户,将所有的业务打成一个应用包放在tomcat容器中运行,与数据库共用一台服务器,这种架构一般称之为单体架构。

    在初期这种架构的效率非常高,根据用户的反馈可以快速迭代上线。但是随着用户量增加,一台服务的内存和CPU吃紧,很容易造成瓶颈,新的问题来了怎么解决呢?

     

    应用与数据分离

    随着用户请求量增加,一台服务器的内存和CPU持续飙升,用户请求响应时间变慢。这时候可以考虑将应用与数据库拆开,各自使用一台服务器,你看问题又解决了吧。

    突然有一天扫地阿姨不小心碰了电线,其中一台服务器掉电了,用户所有的请求都报错,随之而来的是一系列投诉电话。

     

    集群部署

    单实例很容易造成单点问题,比如遇到服务器故障或者服务能力瓶颈,那怎么办?聪明的你肯定想到了,用集群呀。

    集群部署是指将应用部署在多个服务器或者虚机上,用户通过服务均衡随机访问其中的一个实例,从而使多个实例的流量均衡,如果一个实例出现故障可以将其下线,其他实例不受影响仍然可以对外提供服务。

    随着用户数量快速增加,老板决定增加投入扩大团队规模。开发团队壮大后效率并没有得到显著的提高,以前小团队可以一周迭代上线一次,现在至少需要两到三周时间。

    业务逻辑越来越复杂,代码间耦合很严重,修改一行代码可能引入几个线上问题。架构师意识到需要进行架构重构。

     

    微服务架构

    当单体架构演进到一定阶段后开发测试的复杂性都会成本增加,团队规模的扩大也会使得各自工作耦合性更严重,牵一发而动全身就是这种场景。

    单体架构遇到瓶颈了,微服务架构就横空出世了。微服务就是将之前的单体服务按照业务维度进行拆分,拆分粒度可大可小,拆分时机可以分节奏进行。最佳实践是先将一些独立的功能从单体中剥离出来抽成一个或多个微服务,这样可以保障业务的连续性和稳定性。

     

    如上图将一个商用应用拆分为六个独立微服务。六个微服务可以使用Docker容器化进行多实例部署。

    架构演化到这里遇到了一个难题,如果要查询用户所有的订单,用户服务可能会依赖订单服务,用户服务如何与订单服务交互呢?订单服务有多个实例该访问哪一个?

    通常有几种解决办法:

    (1)服务地址硬编码

    服务的地址写死在数据库或者配置文件,通过访问DNS域名进行寻址路由。

    服务B的地址硬编码在数据库或者配置文件中,服务A首先需要拿到服务B的地址,然后通过DNS服务器解析获取其中一实例的真实地址,最后可以向服务B发起请求。

    如果遇到大促活动需要对服务实例扩容,大促完需要对服务实例进行下线,运维人员要做大量的手工操作,非常容易误操作。

    (2)服务动态注册与发现

    服务地址硬编码还有一个非常致命的问题,如果一台实例挂了,运维人员可能不能及时感知到,导致一部分用户的请求会异常。

    引入服务注册与发现组件可以很好解决上面遇到的问题,避免过多的人工操作。

     

    架构演进总结

    在单体架构中一个应用程序就是一个服务包,包内的模块通过函数方法相互调用,模型足够简单,根本没有服务注册和发现一说。

    在微服务架构中会将一个应用程序拆分为多个微服务,微服务会部署在不同的服务器、不同的容器、甚至多数据中心,微服务间要相互调用,服务注册和发现成为了一个不可或缺的组件。

     

    二、服务注册与发现基本原理

    服务注册与发现是分为注册和发现两个关键的步骤。

    服务注册:服务进程在注册中心注册自己的元数据信息。通常包括主机和端口号,有时还有身份验证信息,协议,版本号,以及运行环境的信息。

    服务发现:客户端服务进程向注册中心发起查询,来获取服务的信息。服务发现的一个重要作用就是提供给客户端一个可用的服务列表。

     

    服务注册

    服务注册有两种形式:客户端注册和代理注册。

    客户端注册

    客户端注册是服务自己要负责注册与注销的工作。当服务启动后注册线程向注册中心注册,当服务下线时注销自己。

    这种方式的缺点是注册注销逻辑与服务的业务逻辑耦合在一起,如果服务使用不同语言开发,那需要适配多套服务注册逻辑。

    代理注册

    代理注册由一个单独的代理服务负责注册与注销。当服务提供者启动后以某种方式通知代理服务,然后代理服务负责向注册中心发起注册工作。

    这种方式的缺点是多引用了一个代理服务,并且代理服务要保持高可用状态。

     

    服务发现

    服务发现也分为客户端发现和代理发现。

    客户端发现

    客户端发现是指客户端负责向注册中心查询可用服务地址,获取到所有的可用实例地址列表后客户端根据负载均衡算法选择一个实例发起请求调用。

    这种方式非常直接,客户端可以控制负载均衡算法。但是缺点也很明显,获取实例地址、负载均衡等逻辑与服务的业务逻辑耦合在一起,如果服务发现或者负载平衡有变化,那么所有的服务都要修改重新上线。

    代理发现

    代理发现是指新增一个路由服务负责服务发现获取可用的实例列表,服务消费者如果需要调用服务A的一个实例可以直接将请求发往路由服务,路由服务根据配置好的负载均衡算法从可用的实例列表中选择一个实例将请求转发过去即可,如果发现实例不可用,路由服务还可以自行重试,服务消费者完全不用感知。

     

    心跳机制

    如果服务有多个实例,其中一个实例出现宕机,注册中心是可以实时感知到,并且将该实例信息从列表中移出,也称为摘机。

    如何实现摘机?业界比较常用的方式是通过心跳检测的方式实现,心跳检测有主动被动两种方式。

    被动检测是指服务主动向注册中心发送心跳消息,时间间隔可自定义,比如配置5秒发送一次,注册中心如果在三个周期内比如说15秒内没有收到实例的心跳消息,就会将该实例从列表中移除。

    上图中服务A的实例2已经宕机不能主动给注册中心发送心跳消息,15秒之后注册就会将实例2移除掉。

    主动检测是注册中心主动发起,每隔几秒中会给所有列表中的服务实例发送心跳检测消息,如果多个周期内未发送成功或未收到回复就会主动移除该实例。

     

     

    三、业界常用的服务注册与发现组件对比

    了解服务注册与发现的基本原理后,如果你要在项目中使用服务注册与发现组件,当面对众多的开源组件该如何进行技术选型?

    在互联网公司里,有研发实力的大公司一般会选择自研或者基于开源组件进行二次开发,但是对于中小型公司来说直接选用一款开源软件会是一个不错的选择。

    常用的注册与发现组件有eureka,zookeeper,consul,etcd等,由于eureka在2018年已经宣布放弃维护,这里就不再推荐使用了。

    下面结合各个维度对比一下各组件。

    组件

    优点

    缺点

    接口类型

    一致性算法

    zookeeper

    1.功能强大,不仅仅只是服务发现;

    2.提供watcher机制可以实时获取服务提供者的状态;

    3.广泛使用,dubbo等微服务框架已支持;

    1.没有健康检查;

    2.需要在服务中引入sdk,集成复杂度高;

    3.不支持多数据中心;

    sdk

    Paxos

    consul

    1.开箱即用,方便集成;

    2.带健康检查;

    3.支持多数据中心;

    4.提供web管理界面;

    不能实时获取服务变换通知

    restful/dns

    Raft

    etcd

    1.开箱即用,方便集成;

    2.可配置性强

    1.没有健康检查;

    2.需配合三方工具完成服务发现功能;

    3.不支持多数据中心;

    restful

    Raft

    从整体上看consul的功能更加完备和均衡。接下来以consul为例详细介绍一下。

     

    四、Consul——值得推荐的服务注册与发现开源组件

    简单认识一下Consul

    Consul是HashiCorp公司推出的开源工,使用Go语言开发,具有开箱即可部署方便的特点。Consul是分布式的、高可用的、 可横向扩展的用于实现分布式系统的服务发现与配置。

    Consul有哪些优势?

    • 服务注册发现:Consul提供了通过DNS或者restful接口的方式来注册服务和发现服务。服务可根据实际情况自行选择。
    • 健康检查:Consul的Client可以提供任意数量的健康检查,既可以与给定的服务相关联,也可以与本地节点相关联。
    • 多数据中心:Consul支持多数据中心,这意味着用户不需要担心Consul自身的高可用性问题以及多数据中心带来的扩展接入等问题。

    Consul的架构图

    Consul 实现多数据中心依赖于gossip protocol协议。这样做的目的:

    • 不需要使用服务器的地址来配置客户端;服务发现是自动完成的。
    • 健康检查故障的工作不是放在服务器上,而是分布式的。

     

    Consul的使用场景

    Consul的应用场景包括服务注册发现服务隔离服务配置等。

    服务注册发现场景中consul作为注册中心,服务地址被注册到consul中以后,可以使用consul提供的dns、http接口查询,consul支持health check。

    服务隔离场景中consul支持以服务为单位设置访问策略,能同时支持经典的平台和新兴的平台,支持tls证书分发,service-to-service加密

    服务配置场景中consul提供key-value数据存储功能,并且能将变动迅速地通知出去,借助Consul可以实现配置共享,需要读取配置的服务可以从Consul中读取到准确的配置信息。

     

    -- END --

    日常求赞:你好技术人,先赞后看养成习惯,你的赞是我前进道路上的动力,对我非常重要。

    加油技术人!

    简介: 博主从华中科技大学硕士毕业,是一个对技术有追求,对生活有激情的程序员。几年间浪迹于多个一线互联网大厂,具有多年开发实战经验。

    微信搜索公众号【爱笑的架构师】,我有技术和故事,等你来。

    文章持续更新,在 Github/javamap 中可以看到我归档的系列文章,有面试经验和技术干货,欢迎Star。

     

    展开全文
  • 服务发现服务注册

    千次阅读 2018-06-10 10:17:52
    一 硬编码问题1 适用场景有局限:如果服务提供者的网络地址(IP和端口)发生了变化,将会影响服务消费者。例如,用户微服务的网络地址发生了变化,就需要修改电影微服务的配置,...二 服务发现服务提供者、服务消...
    一 硬编码问题
    1 适用场景有局限:如果服务提供者的网络地址(IP和端口)发生了变化,将会影响服务消费者。例如,用户微服务的网络地址发生了变化,就需要修改电影微服务的配置,并重新发布,这显然不可取。
    2 无法动态伸缩:在生产环境中,每个微服务一般都会部署多个实例,从而实现容灾和负载均衡。在微服务的系统中,还需要具备自动伸缩的能力,例如动态增减节点。硬编码无法适应这种需求。
    二 服务发现
    服务提供者、服务消费者、服务发现组件这三者之间的关系如下
    1 各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息。
    2 服务消费者可从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者接口。
    3 各个微服务与服务发现组件使用一定机制(例如心跳)通信。服务发现组件如长时间无法与某微服务实例通信,就会注销实例。
    4 微服务网络地址发生变更(例如实例增减或者IP端口发生变化等)时,会重新注册到服务发现组件。使用这种方式,服务消费者就无须人工修改提供者的网络地址了。
    三 服务发现组件的功能
    1 服务注册表
    服务注册表是一个记录当前可用服务实例的网络信息的数据库,是服务发现机制的核心。它用来记录各个微服务的信息,例如微服务的名称、IP、端口等。服务注册表提供查询API和管理API,使用查询API获得可用的服务实例,使用管理API实现注册和注销。
    2 服务注册和服务发现
    服务注册是微服务在启动时,将自己的信息注册到服务发现组件上的过程。服务发现是指查询可用微服务列表及网络地址的机制。
    3 服务检查
    服务发现组件使用一定机制定时检测已注册的服务,如发现某实例长时间无法访问,就会从服务注册表中移除该实例。
    四 服务发现的方式
    客户端发现:Eureka、zk
    服务端发现:Consul+nginx

    展开全文
  • 【BLE】CC2541之发现服务与特征值

    万次阅读 2015-07-16 12:33:08
    本文以SimpleBLECentral工程为例,介绍CC2541作为主机时是如何发现从机的服务和特征值的

    本篇博文最后修改时间:2017年01月06日,11:06。


    一、简介

    本文以SimpleBLECentral工程为例,解析CC2541作为主机时是如何发现从机的服务和特征值的。


    二、实验平台

    协议栈版本:BLE-CC254x-1.4.0

    编译软件:IAR 8.20.2

    硬件平台:Smart RF(主芯片CC2541)


    三、版权声明

    博主:甜甜的大香瓜

    声明:喝水不忘挖井人,转载请注明出处。

    原文地址:http://blog.csdn.NET/feilusia

    联系方式:897503845@qq.com

    香瓜BLE之CC2541群:127442605

    香瓜BLE之CC2640群:557278427

    香瓜BLE之Android群:541462902

    香瓜单片机之STM8/STM32群:164311667
    甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

    四、 实验前提
    1、在进行本文步骤前,请先 阅读 以下博文:
    暂无

    2、在进行本文步骤前,请先 实现以下博文:
    暂无


    五、基础知识

    1、服务和特征值是什么?

    答:

    一个工程可以有多个服务,比如按键服务、心率计服务、温度计服务。

    一个服务可以有多个特征值,特征值是主从机传输数据的媒介,像运人渡河的小船。

    如果主机要想获得按键服务的特征值,必须先发现按键服务、再获得按键服务的特征值句柄、再根据特征值句柄获取特征值。


    六、代码解析

    1、启动发现服务事件

    在连接完成时,主机会判断是否之前获取过特征值句柄,如果没有获取到,则调用定时器进“START_DISCOVERY_EVT事件”开始发现服务。


    2、发现服务事件


    3、发现服务的函数

    默认发现的是UUID为FFF0的服务。


    4、发现服务的回调函数

    发现服务后,就会进入该函数。

    此时可以通过特征值的UUID来读取对应的特征值句柄。默认的是读取CHAR1的特征值句柄。


    5、获得特征值句柄

    读到特征值句柄后会再次进入该回调函数,此时将特征值句柄保存下来,随口可用来操作特征值。


    展开全文
  • 自android 4.1 开始实现了一个网络服务的发现服务NsdService,其基于苹果的Bonjour服务发现协议,支持远程服务的发现和零配置。  Bonjour协议包括IP地址的自动分配、服务名称与地址的转换以及服务的发现三部分内容...

              自android 4.1 开始实现了一个网络服务的发现服务NsdService,其基于苹果的Bonjour服务发现协议,支持远程服务的发现和零配置。

            Bonjour协议包括IP地址的自动分配、服务名称与地址的转换以及服务的发现三部分内容,ANDROID4.1借助第三方开源工程mDNSResponder实现了Bonjour协议的服务名称与地址的转换以及服务的发现等 Bonjour部分协议的支持。Bonjour协议的服务名称与地址的转换以及服务的发现采用的流程和DNS流程近似包括:登记过程、服务发现过程、服务地址解析过程以及建立连接等过程,服务发现采用的协议也和DNS协议相似,不过与DNS协议采用的单播方式不同的是采用了组播方式,因此被称为mDNS。

                               

                                




             ANDROID4.2 对网络服务发现的实现架构包括四层:NSD应用客户端、服务发现服务框架层(对应NsdService)、MDns后台监视层(对应运行在netd本地服务进程的MDnsSdListener类 )以及MDns后台服务(对应mdnsd本地服务进程)。架构的每层作为其上一层的服务端对上一层提供服务,上层通过connect与下层服务建立连接。其中NsdService 和NSD应用客户端采用JAVA语言实现 ,MDns后台监视采用C++实现,而MDns后台服务为采用C语言的开源代码。四层分别运行在不同的进程,采用相应的跨进程通讯方式进行交互。

      NsdService处于整个层次的承上启下层,其通过NsdManager对上层应用客户端提供调用和回调服务,NsdManager客户和NsdService服务之间采用AsyncChannel异步通道进行消息交互。NsdService服务对下在其NativeDaemonConnector线程对象中使用UNIX SOCKET接口与MDns后台监视层建立跨进程连接,传输命令和接收响应,MDns后台监视层的MDnsSdListener对象运行在netd本地服务中。

       在MDnsSdListener类中调用mDNSResponder开源工程提供的客户端桩接口与MDns后台服务建立本地SOCKET通讯,并采用Monitor对象来启动MDns后台服务,实现MDns后台服务的事件监听和事件回调处理等工作。MDnsSdListener及Monitor对象与MDns后台服务的交互也是采用UNIX SOCKET机制进行跨进程交互。

      MDns后台服务的整个实现代码及客户端的桩实现由第三方工程mDNSResponder提供,代码位于 external目录下 的mdnsresponder中,包括mDNSCore(包括MDNS核心协议引擎代码)、mDNSShared多个平台共享的非核心引擎代码、mDNSPosix  Posix平台相关代码、Clients包括如何使用后台服务提供的API的客户端例子代码等四个目录,整个工程编译生成一个mdnsd后台服务和一个MDns监视层使用的库libmdnssd,而Clients中的代码生成一个dnssd执行文件用于测试。

             一个应用为了让网络上的其它应用发现它需要通过网络声明自己,即服务登记,这通过调用NsdManager的registerService接口实现。

               下面分步骤描述服务登记流程。

     1、应用通过调用Context.getSystemService(Context.NSD_SERVICE)获得NsdManager的实例。

      在NsdManager的实例化过程中对使用到的资源进行实例化,包括调用NsdService的getMessenger函数获得服务的Messenger对象用作客户端消息的发送目标,实例化和启动事件处理线程HandlerThread及实例化事件接收处理对象ServiceHandler,AsyncChannel对象的实例化并且调用AsyncChannel对象的connect函数与目标建立连接。

     在NsdService服务接收到连接消息后,实例化一个服务端的AsyncChannel对象,并根据消息的源和服务端的AsyncChannel对象实例化一个ClientInfo对象放入mClients HashMap数组中。

         2、应用调用NsdManager实例的registerService接口,registerService接口参数中包含一个NsdServiceInfo参数(指示要登记的服务信息)、一个protocolType参数(指定协议类型)以及一个监听对象listener,用来接收响应事件回调。

       在registerService接口中调用putListener函数分别把NsdServiceInfo参数和监听对象listener保存到mServiceMap和mListenerMap的映射数组中,并返回数组的键值key;然后registerService通过NsdManager的AsyncChannel对象向目标发送REGISTER_SERVICE消息,发送的消息参数包括putListener函数返回的key以及NsdServiceInfo信息。

         3、NsdService服务收到REGISTER_SERVICE消息后,首先根据消息源从mClients数组中获得clientInfo对象,然后调用getUniqueId获得一个UniqueId作为登记请求ID;接着调用服务端的registerService函数,registerService的参数为UniqueId和消息传进来的NsdServiceInfo信息。在registerService函数中调用NativeDaemonConnector对象的execute函数,execute函数的命令参数为”mdnssd”,其它参数包括登记命令名称标示"register"、登记ID、从NsdServiceInfo中获得的ServiceName、ServiceType和port等参数。

       NativeDaemonConnector对象在NsdService服务实例化时实例化, NativeDaemonConnector对象实例化mSocket参数为"mdns",mCallbacks参数指向NsdService服务内部NativeCallbackReceiver对象。NativeDaemonConnector对象本身是一个派生自Runnable的线程对象,因此其线程函数run也在实例化后启动。

     在run函数中首先实例化和启动了一个事件处理线程HandlerThread及其事件处理Handler,接着进入while循环调用listenToSocket函数。

        listenToSocket首先实例化一个本地socket对象,LocalSocket对象的LocalSocketAddress地址的 Socket名称为已初始化的mSocket,并使用该地址调用connect函数,从init.rc 可以看到名称为"mdns"的Socket对应的本地服务为netd,因此NativeCallbackReceiver对象与netd服务建立了连接;然后listenToSocket函数调用socket的getInputStream和getOutputStream函数获得输入和输出流对象;最后listenToSocket函数进入while循环不断从输入流读取事件进行分析。解析后的事件发给HandlerThread线程的Handler函数进行处理,在Handler函数中调用mCallbacks的onEvent回调函数,即NsdService服务内部NativeCallbackReceiver对象的onEvent回调函数。

        4、在NativeDaemonConnector对象的execute函数中首先根据传进的参数调用makeCommand函数生成一个字符串类型的命令,然后调用本地socket的输出流对象 mOutputStream的write函数来发送命令。

        5、在本地服务netd的进程中调用其MDnsSdListener对象的startListener函数启动命令的监听。

     MDnsSdListener对象通过FrameworkListener间接派生自SocketListener,在MDnsSdListener对象实例化时其成员mSocketName初始化 为"mdns",因此对应的socket通道和NativeCallbackReceiver对象中的socket通道相同。MDnsSdListener实例化时还初始化一个Monitor对象和一个FrameworkCommand类型的Handler对象。

     Handler对象初始化时其mCommand属性赋值为"mdnssd",用来和发送来的命令匹配,Handler对象也保存到FrameworkCommand命令列表对象中mCommands。

    Monitor对象实例化时调用socketpair函数建立一个Socket组mCtrlSocketPair,还创建一个监听线程,线程中调用Monitor对象的run函数。

         6、startListener函数首先调用android_get_control_socket函数根据mSocketName名称获得其SOCKET fd;然后调用listen函数监听socket通道;

        然后创建一个线程,在线程中执行runListener函数,在runListener函数循环调用accept接收客户端连接。当有客户端连接后,根据accept返回的socket fd实例化一个SocketClient对象保存到SocketClient对象列表中mClients,并调用onDataAvailable函数。

             onDataAvailable函数调用read函数读取客户端发送的命令,并调用dispatchCommand函数提交命令。

      在dispatchCommand函数中解析命令参数,并与mCommands命令对象列表进行命令匹配,并调用匹配后命令对象的runCommand函数,这里即调用MDnsSdListener对象中的Handler对象的runCommand函数。

        7、在Handler对象的runCommand函数中进行命令参数的匹配,这里匹配的是"register",因此在获得命令参数后调用serviceRegister函数,serviceRegister函数参数包括匹配的SocketClient对象以及命令参数信息。

        8、在serviceRegister函数中,首先调用mMonitor的allocateServiceRef函数根据请求ID实例化一个Element对象放入链表中,并返回Element对象的DNSServiceRef指针,DNSServiceRef指向_DNSServiceRef_t结构,其成员包括DNS操作或应答类型,接收消息回调接口、客户端回调和上下文、客户端与服务端连接socket等参数。

      然后调用DNSServiceRegister函数,DNSServiceRegister函数用来向本地MDns后台服务发起连接和消息请求,DNSServiceRegister函数的参数包括allocateServiceRef函数返回的DNSServiceRef指针变量以及serviceRegister传进来的命令请求参数,以及事件接收回调函数MDnsSdListenerRegisterCallback。

    在DNSServiceRegister函数调用后接着调用mMonitor的startMonitoring函数,参数为请求ID,startMonitoring函数用来准备与服务器已建立连接的SOCKET监视通道和启动监视通道的监听。最后调用SocketClient对象的sendMsg函数向客户端返回CommandOkay应答消息。

            9、DNSServiceRegister函数为mDNSResponder开源工程提供的客户端调用API接口,用来与MDns后台服务建立连接,并向其提交请求。

            在DNSServiceRegister函数中首先通过ConnectToServer函数与MDns后台服务建立连接。

    在ConnectToServer函数首先实例和初始化一个_DNSServiceRef_t类型DNSServiceOp变量,然后创建一个本地socket,且新建socket的文件句柄赋值给DNSServiceOp对象的sockfd。   

            然后调用connect与MDns后台服务建立连接,最后把实例化后的DNSServiceOp对象通过DNSServiceRef参数带回。

        ConnectToServer函数返回后接着调用create_hdr函数为实例化一个ipc_msg_hdr类型的请求消息,并对请求消息赋值后连同ConnectToServer函数带回的DNSServiceRef参数一同传给deliver_request函数,通过deliver_request函数提交请求。

             10 、在Monitor对象的run函数中循环对mPollFds进行poll操作。

      在startMonitoring函数通过向mCtrlSocketPair[1]写入RESCAN命令后,由于mPollFds[0].fd指向mCtrlSocketPair[0],因此mMonitor的run函数在mPollFds[0]通道读取到RESCAN命令并调用RESCAN函数,在RESCAN函数中根据已建立的与服务器的连接为mPollFds的其它通道赋值,这些mPollFds通道的文件句柄位赋值为服务器已建立连接的socket 的句柄。

        在服务端的响应事件到来时在这些通道poll到事件,然后调用DNSServiceProcessResult函数,参数为DNSServiceRef。

           11、 在DNSServiceProcessResult函数中读取响应事件和数据,并调用DNSServiceRef参数的事件回调ProcessReply函数,即对于服务登记请求对应的是MDnsSdListenerRegisterCallback函数。

     在MDnsSdListenerRegisterCallback中向Handler对象的监听对象的sendBroadcast函数发送ResponseCode::ServiceRegistrationSucceeded应答消息,Handler对象的监听对象为MDnsSdListener对象本身,因此这里调用SocketListener的sendBroadcast函数。

    在sendBroadcast函数中遍历mClients对象的成员对象,并调用其调用sendMsg函数,即调用SocketClient的sendMsg函数。

    在sendMsg函数中通过与客户端(即NsdService服务的NativeDaemonConnector对象)建立的SOCKET向客户端发送应答消息。

          12、在NsdService的NativeDaemonConnector对象的listenToSocket函数 收到服务端的应答消息后,调用NsdService服务内部NativeCallbackReceiver对象的onEvent回调函数。

    在onEvent回调函数中向NsdService服务的状态机发送NsdManager.NATIVE_DAEMON_EVENT事件,假如这时NsdService服务处于EnabledState状态,状态机收到NsdManager.NATIVE_DAEMON_EVENT事件后调用handleNativeEvent函数。 

     handleNativeEvent函数首先根据响应消息的请求ID从mIdToClientInfoMap中获得先前客户端建立连接时保存的clientInfo对象及从clientInfo对象获得clientId,然后执行响应事件代码为NativeResponseCode.SERVICE_REGISTERED的事件处理,事件处理先根据返回的响应事件实例化一个NsdServiceInfo对象,然后通过clientInfo中的AsyncChannel对象成员向NsdService服务的客户端发送NsdManager.REGISTER_SERVICE_SUCCEEDED响应事件。

     13、NsdManager的事件接收对象ServiceHandler接收到NsdManager.REGISTER_SERVICE_SUCCEEDED响应事件,在其handleMessage函数中调用其监听对象(NSD应用客户端)的onServiceRegistered回调。到此整个服务登记流程结束。

             服务发现和服务地址解析流程采用服务登记流程基本相同的流程。在服务发现和服务地址解析后就可以向服务收发数据了。

                                                                                                              

                                                                                                                版权所有,转载时请尊重原创显要处注明链接,谢谢!

    第十七篇 --ANDROID DisplayManager 服务解析一

     第十五篇 Android 的Backup服务管理机制--助手模式

    
    展开全文
  • 如何理解服务注册和服务发现

    千次阅读 2019-05-06 11:49:28
    三者的关系是:通过服务注册机制将启动服务的信息上传至服务注册表,服务发现机制通过服务注册表实时获取可用服务的信息。 服务注册的方式包括:自注册和第三方注册。自注册的意思是当服务启动时,服务自动将信息...
  • go 使用consul实现服务注册发现

    万次阅读 2020-02-09 16:36:29
    目标 既然是学习使用consul实现服务注册发现,目标自然是实现一个程序,可以通过consul,发现另一个程序。...3.本机(mac):运行一个程序,可以通过云服务器A上的consul,发现云服务器B上的服务 启动cons...
  • 关于Docker的服务发现与注册

    千次阅读 2017-07-26 21:30:38
    但是在最近一段时间,随着Docker和微服务架构的迅速发展,服务连接趋于动态化,服务的位置(IP和端口号)变化会非常频繁,动态服务注册和发现变得越来越重要,因此,越来越多的人开始关注服务发现服务发现的目的...
  • Spring cloud服务发现服务提供者和服务消费者 1.服务提供者 2.服务提供者 3.启动运行 4.综上 1.服务提供者根据上节讲述的服务注册之Eureka注册中心,这节讲述服务提供者和服务消费者,首先新建一个工程,...
  • 深入浅出prometheus之服务发现(sd)

    万次阅读 2018-08-07 11:31:00
    syncCh chan map[string][]*targetgroup.Group // 与外部交互chan,当发现服务变化是把全量的在线服务发从到chan中 recentlyUpdated bool // 有服务更新的标记 recentlyUpdatedMtx sync.Mutex // 服务更新用的锁 ...
  • 浅谈服务发现

    万次阅读 多人点赞 2017-08-27 09:19:13
    这片文章简单地介绍了服务发现,包括服务发现的两种模式,以及Eureka(偏向于AP)以及Consul(偏向于CP)两个微服务框架。
  • 服务A调用服务B时,需要通过服务发现模块找到服务B的IP和端口列表,而服务B的实例在启动时需要把提供服务的IP和端口注册到服务注册中心。一个典型的结构如下图: 也即是说,ServiceA需要通过查找ServiceRegistry...
  • PHP实现consul服务注册与服务发现

    千次阅读 2019-04-18 22:04:31
    本文主要介绍怎么用consul提供的HTTP的API来实现PHP与consul之间的通信,实现服务的注册与发现。 首先官方API:https://www.consul.io/api/index.html 其次我实现的代码:...
  • spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单,可以在开发人员的电脑上跑。另外说明...
  • 1. 创建自动发现 配置->自动发现->创建发现规则 设置名称 配置IP范围 设置延迟时间 设置IP地址为唯一性准则 启用发现规则 2. 创建动作 配置->动作->创建动作 2.1 设置...
  • SSDP,简单服务发现技术

    千次阅读 2016-07-25 16:23:15
    SSDP:Simple Sever Discovery Protocol,简单...协议客户端在保留的多播地址:239.255.255.250:1900(IPV4)发现服务,(IPv6 是:FF0x::C)同时每个设备服务也在此地址上上监听服务发现请求。如果服务监听到的发现请
  • Istio:服务发现和Pilot的架构机制

    千次阅读 2020-01-11 23:03:09
    Istio服务发现 Istio服务配置 stio服务发现&规则管理与Kubernetes结合 ShowCase Istio架构&Pilot介绍 Istio架构 Pilot功能 服务发现 服务配置 Istio服务发现 服务发现基本原理 a.app 88.88....
  • 使用Nacos实现服务注册与发现

    千次阅读 2019-01-18 10:05:46
    Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现服务配置、服务元数据及流量管理。Nacos帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos是构建以“服务”为中心的现代应用架构 (例如微服务...
  • springcloud如何实现服务的注册和发现

    千次阅读 2019-03-17 22:09:16
    服务在发布时指定对应的服务名(服务名包括了IP地址和端口)将服务注册到注册中心(eureka或者zookeeper...调用方法:传递服务名称通过注册中心获取所有的可用实例通过负载均衡策略调用(ribbon和feign)对应的服务...
  • <蓝牙BLE>cc2541发现服务与特征值

    千次阅读 2015-11-05 22:27:50
    声明,本文转载自“甜甜的大香瓜”的博客,原文地址如下: ...本篇以SimpleBLECentral工程为例,解析CC2541作为主机时是如何发现从机的服务和特征值的。 二、实验平台 协议栈版本:BLE-CC254x-1.3.2 编译软件:I
  • Zuul、Fegin、Rebbion、Eureka一条龙很多人都自然而然把zuul当成nginx那样来在配置写死节点配置来。...下文将介绍静态配置路由表和从Eureka发现服务的两种方式来加强Zuul的使用。项目地址:AG-Admin:http
  • 基于Zookeeper服务注册和发现

    万次阅读 2017-01-14 15:46:53
    2、基于zk服务注册和发现的架构图   3、服务端(像zk提供服务的访问地址) package cn.zk.distribute; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache....
  • 服务注册中心---服务发现nacos

    万次阅读 2021-07-15 16:05:09
    服务在nacos是一等公民 二、有了Eureka为啥还要用nacos?两者区别是什么? 具体可看这篇文章 很形象 三、下载安装 可参考里面的下载安装流程 比较简单 四、nacos原理 Nacos注册中心分为server与client,server采
  •  Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,比如 Airbnb的SmartStack等相比,Consul的方案更“一站式”,内置了服务注册与发现框 架、分布...
  • Consul服务注册与服务发现机制

    千次阅读 2019-06-25 15:43:02
    1、什么是服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相调用。...现在订单服务是想要调用库存服务,但是他并不知道库存服务在...
  • 为什么不用ZK来做服务发现

    千次阅读 2016-11-23 14:45:20
    本文作者通过ZooKeeper与Eureka作为 Service发现服务的优劣对比,分享了Knewton在云计算平台部署服务的经验。本文虽然略显偏激,但是看得出Knewton在云平台方面是非常有经验的,这篇文章从实践角度出发分别从云平台...
  • 在Server3宕机时,Server2当时还保存着ClientC的服务信息,在那个时间,其他服务还是能通过Server2发现ClientC的,但是因为ClientC的不能续约,在90S后Server2将删除ClientC的服务信息。ClientC与服务集群基本隔离。...
  • 为什么要使用服务发现

    千次阅读 2018-03-01 16:40:40
    为什么要使用服务发现?假设我们写的代码会调用 REST API 或者 Thrift API 的服务。为了完成一次请求,代码需要知道服务实例的网络位置(IP 地址和端口)。运行在物理硬件上的传统应用中,服务实例的网络位置是相对...
  • 使用 Avahi 命令行程序发现服务

    千次阅读 2014-01-16 09:56:32
    使用 Avahi 命令行程序发现服务 如果您使用的是 Linux 计算机,那么您可以使用 Avahi 来浏览以查找本地网络上广播的服务。 准备工作: 您必须安装适用于您所用的 Linux 操作系统的 Avahi RPM 包,然后才能使用...
  • 华为云讲解:2.Istio Pilot 与...文章目录华为云讲解:2.Istio Pilot 与服务发现服务发现看图说话 在Istio里面Service A 访问ServiceB 如何做到的服务发现的实现Istio 结合Kubernetes 做服务发现总结配置管理流量规则...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,115,877
精华内容 846,350
关键字:

发现服务