[ZooKeeper.net] 1 模仿dubbo实现一个简要的http服务的注册 基于webapi

今天来试着模仿下dubbo实现一个简要的http服务的注册,虽说是模仿不过是很廉价的那种,只是模仿了一点点点......

先放上demo目录结构:

开头还是把ZooKeeper的一些简要介绍搬过来看看,这样让大家也能多了解点儿:

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等。Zookeeper是hadoop的一个子项目,其发展历程无需赘述。在分布式应用中,由于工程师不能很好地使用锁机制,以及基于消息的协调机制不适合在某些应用中使用,因此需要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。Zookeeper的目的就在于此。

      Zoopkeeper 提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而可以设计出多种多样的分布式的数据管理模型。

OK,更多介绍大家自行搜索吧,主要点【基于层次型的目录树的数据结构,并对树中节点进行有效管理】,这句话是不是可以理解就是树形结构,我也放个图,省的还要大家脑补......

ps.有关ZooKeeper的安装不管是windows还是linux不论是单机还是集群网上一搜好多的,我用的zookeeper-3.4.6 windows版的

首先我们要获取到ZooKeeper.Net的客户端

首先定义个IZooKeeperFactory

    public interface IZooKeeperFactory
    {
        ZooKeeper Connect(string address);
        ZooKeeper Connect(string address, TimeSpan timeoutSpan);
        ZooKeeper Connect(string address, TimeSpan timeoutSpan, IWatcher watcher);
        ZooKeeper Connect(string address, TimeSpan timeoutSpan, IWatcher watcher, long sessionId, byte[] password);
    }

然后ZooKeeperFactory 和 Watcher

 public sealed class ZooKeeperFactory : IZooKeeperFactory
    {
        public static IZooKeeperFactory Instance = new ZooKeeperFactory();
        private ZooKeeperFactory() { }
        //创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,第二个参数为Session超时时间,第三个为节点变化时的回调方法
        public ZooKeeper Connect(string address)
        {
            return Connect(address, new TimeSpan(0, 0, 0, 30), new Watcher());
        }
        public ZooKeeper Connect(string address, TimeSpan timeoutSpan)
        {
            return Connect(address, timeoutSpan, new Watcher());
        }
        public ZooKeeper Connect(string address, TimeSpan timeoutSpan, IWatcher watcher)
        {
            return new ZooKeeper(address, timeoutSpan, watcher);
        }
        public ZooKeeper Connect(string address, TimeSpan timeoutSpan, IWatcher watcher, long sessionId, byte[] password)
        {
            return new ZooKeeper(address, timeoutSpan, watcher, sessionId, password);
        }
    }

ZooKeeperFactory

 internal class Watcher : IWatcher
    {
        public void Process(WatchedEvent @event)
        {
            if (@event.Type == EventType.NodeChildrenChanged)
            {
                // Console.WriteLine(@event.Path + "   此路径节点变化了!");
            }
            if (@event.Type == EventType.NodeDataChanged)
            {
                // Console.WriteLine(@event.Path + "   此路径节点变化了!");
            }
            if (@event.Type == EventType.NodeDeleted)
            {
                // Console.WriteLine(@event.Path + "   此路径节点变化了!");
            }

        }
    }

Watcher

以上直接用于创建Zookeeper的实例,各个参数代码中也写了说明

然后我们创建UserServicesController 里面写了两个服务 1.User/sayhello  2.User/saybye

public class UserServicesController : ApiController
    {
        [Route("User/sayhello")]
        public string sayhello()
        {
            return "hello world!";
        }
        [Route("User/saybye")]
        public string saybye()
        {
            return "byebye world!";
        }
    }

我们最终要实现的结果是这样子的:【x】只是为了起到标示作用

︱-------【1】UserServices
     ︱-----------【1.1】User.sayhello 
     ︱----------------【1.1.1】192.168.0.1:80 
     ︱----------------【1.1.2】192.168.0.2:80 
     ︱-----------【1.2】User.saybye 
     ︱----------------【1.2.1】192.168.0.1:81 
     ︱----------------【1.2.2】192.168.0.2:81

接下来来看看最主要的一个类 ScanConfig.cs

先说下大概逻辑:

1.初始化zk客户端

2.将服务名称UserServices 注册为主节点 (永久节点)

3.获取所有webapi服务路径 例如:User/saybye

4.循环将所有服务路径注册为zk节点(永久节点)   读取服务器IP地址(临时节点 会话断开 节点自动消失) 注册到 每个服务节点下

下面把代码贴一下,代码中也有注释,最后会给出demo

 public class ScanConfig
    {

        private String connectString = "127.0.0.1:2181";
        private ZooKeeper zk = null;
        public ScanConfig()
        {
            init();
        }
        public void init()
        {
            try
            {
                //初始化zk客户端
                buildZKclient();
                //绑定服务父节点  services名称
                registBiz();
                //得到所有服务地址
                List<String> services = getServicePath();
                //把服务注册到zk
                registBizServices(services);
            }
            catch (Exception)
            {
                //日志记录
            }
        }

        /// <summary>
        /// 初始化连接
        /// </summary>
        private void buildZKclient()
        {
            IZooKeeperFactory _factory = ZooKeeperFactory.Instance;
            zk = _factory.Connect(connectString, new TimeSpan(0, 0, 0, 30));
        }

        /// <summary>
        /// 绑定父节点
        /// </summary>
        private void registBiz()
        {
            if (zk.Exists("/" + WebApiConfig.bizCode, true) == null)
            {
                //创建一个目录节点,不进行ACL权限控制,节点为永久性的
                zk.Create("/" + WebApiConfig.bizCode, ("Test:" + WebApiConfig.bizCode).GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
            }
        }
        /// <summary>
        ///   通过注解得到所有Api服务地址
        /// </summary>
        /// <returns></returns>
        private List<String> getServicePath()
        {
            List<String> PathString = new List<string>();
            Collection<ApiDescription> ApiString = GlobalConfiguration.Configuration.Services.GetApiExplorer().ApiDescriptions;
            foreach (var api in ApiString)
            {
                PathString.Add(api.RelativePath.Replace("/", "."));
            }
            return PathString;
        }
        /// <summary>
        ///  把服务注册到zk
        /// </summary>
        /// <param name="Services">所有Api服务地址</param>
        private void registBizServices(List<String> Services)
        {
            //获取服务IP地址端口
            IPAddress[] IPList = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList;
            string hostName = IPList[0].ToString();
            //创建临时节点 会话断开 节点自动消失
            foreach (var apiname in Services)
            {
                if (zk.Exists("/" + WebApiConfig.bizCode + "/" + apiname, true) == null)
                {
                    //创建一个目录节点,不进行ACL权限控制,节点为永久性的   服务名称
                    zk.Create("/" + WebApiConfig.bizCode + "/" + apiname, ("Test:" + WebApiConfig.bizCode).GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
                }
                //创建一个目录节点,不进行ACL权限控制,节点为临时性的  服务提供者ip地址
                zk.Create("/" + WebApiConfig.bizCode + "/" + apiname + "/" + hostName, ("Test:" + WebApiConfig.bizCode).GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Ephemeral);
            }
        }

    }

ScanConfig

最后Global.asax中 Application_Start方法加入就OK了

ScanConfig scan = new ScanConfig();

有关注册后节点过一段时间消失的问题可以参考下 _xxy 的http://www.cnblogs.com/xxyBlogs/p/5538583.html 这篇文章。

之前做过一个webservices接口里面有一些数据是调用别的项目的webservices接口,然后第一次访问这个接口处理时间老是很慢,处理方法跟 _xxy 这种处理大体一致,因为iis有闲时超时跟回收设置,所以到时间或回收后,webservices的xml序列化的操作需要从新做,所以调用很耗时,不过往往都是第一次很耗时,序列化过完后面就变的很快,加上当是部署了六台,不定那一台就处于闲时状态,当是就因为这个问题项目耽搁好几天没上线,后来设置了iis的闲时超时跟回收设置,又写了个页面,页面的load事件访问一下webservices,然后Application_Start的时候就启动一个定时器,设置一定时间后就http get一下这个页面,等于也是让序列化的过程在不知不觉中处理掉,这样有实际业务来的时候序列化的操作不用做了,耗时的问题也不存在了,项目也成功上线了,希望能帮助到有此类问题的童鞋哈!

demo下载:http://pan.baidu.com/s/1bpxifJx

时间: 2024-08-05 11:10:11

[ZooKeeper.net] 1 模仿dubbo实现一个简要的http服务的注册 基于webapi的相关文章

zookeeper伪集群+dubbo

一.简介 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地 松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提 供方(Provider)和服务消费方(Consumer)两个角色.关于注册中心.协议支持.服务监控等内容. 主要核心部件: * Remoting: 网络通信框架,实现了 sync-over-async 和 r

【Dubbo&amp;&amp;Zookeeper】1、Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)

转自:http://blog.csdn.net/congcong68/article/details/41113239 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架,在这种情况下诞生的.现在核心业务抽取出来,作为独立的服务,使前端应用能更快速和稳定的响应. 第一:介绍Dubbo背景 大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用

自己动手写RPC框架到dubbo的服务动态注册,服务路由,负载均衡功能实现

RPC即远程过程调用,它的实现方式有很多,比如webservice等.框架调多了,烦了,没激情了,我们就该问自己,这些框架的作用到底是什么,来找回当初的激情. 一般来说,我们写的系统就是一个单机系统,一个web服务器一个数据库服务,但是当这单台服务器的处理能力受硬件成本的限制,是不能无限的提升处理性能的.这个时候我们使用RPC将原来的本地调用转变为调用远端的服务器上的方法,给系统的处理能力和吞吐量带来了提升. RPC的实现包括客户端和服务端,即服务的调用方和服务的提供方.服务调用方发送rpc请求

【转】Dubbo是Alibaba开源的分布式服务框架

Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色.关于注册中心.协议支持.服务监控等内容,详见后面描述. 总体架构 Dubbo的总体架构,如图所示: Dubbo框架设计一共划分了10个层,而最上面的Serv

RPC原来就是socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化

序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用. RPC即远程过程调用,它的实现方式有很多,比如webservice等.框架调多了,烦了,没激情了,我们就该问自己,这些框架的作用到底是什么,来找回当初的激情. 一般来说,我们写的系统就是一个单机系统,一个web服务器一个数据库服务,但是当这单台服务器的处理能力受硬件成本的限制,是不能无限的提升处理性能的.这个时候我们使用RPC将原来的本地调

Dubbo原理和源码解析之服务暴露

一.框架设计 在官方<Dubbo 用户指南>架构部分,给出了服务调用的整体架构和流程: 另外,在官方<Dubbo 开发指南>框架设计部分,给出了整体设计: 以及暴露服务时序图: 本文将根据以上几张图,分析服务暴露的实现原理,并进行详细的代码跟踪与解析. 二.原理和源码解析 2.1 标签解析 从文章<Dubbo原理和源码解析之标签解析>中我们知道,<dubbo:service> 标签会被解析成 ServiceBean. ServiceBean 实现了 Init

Dubbo搭建HelloWorld-搭建服务提供者与服务消费者并完成远程调用(附代码下载)

场景 Dubbo简介与基本概念: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103555224 Dubbo环境搭建-ZooKeeper注册中心: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103555470 Dubbo环境搭建-管理控制台dubbo-admin实现服务监控: https://blog.csdn.net/BADAO_LIUMANG_QI

手写一个模块化的 TCP 服务端客户端

前面的博客 基于 socket 手写一个 TCP 服务端及客户端 写过一个简单的 TCP 服务端客户端,没有对代码结构进行任何设计,仅仅是实现了相关功能,用于加深对 socket 编程的认识. 这次我们对整个代码结构进行一下优化,使其模块化,易扩展,成为一个简单意义上的“框架”. 对于 Socket 编程这类所需知识偏底层的情况(OS 协议栈的运作机制,TCP 协议的理解,多线程的理解,BIO/NIO 的理解,阻塞函数的运作原理甚至是更底层处理器的中断.网卡等外设与内核的交互.核心态与内核态的切

一个简单的WCF服务

以订票为例简单应用wcf程序,需要的朋友可以参考下 WCF实例(带步骤) 复制代码代码如下: <xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 本篇转自百度文档,自己试过,确实可以用. 以订票为例简单应用wcf 新建一个wcf服务应用程序 在IService1.cs定义服务契约 复制代码代码如下: namespace WcfDemo { // 注意: 如果