今天来试着模仿下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(, , , ), 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(, , , ));
} /// <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[].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

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

  1. 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务

    来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...

  2. 使用 SpringBoot+Dubbo 搭建一个简单分布式服务

    实战之前,先来看几个重要的概念 开始实战之前,我们先来简单的了解一下这样几个概念:Dubbo.RPC.分布式.由于本文的目的是带大家使用SpringBoot+Dubbo 搭建一个简单的分布式服务,所以 ...

  3. Soa: 一个轻量级的微服务库

    Soa 项目地址:Github:MatoApps/Soa 介绍 一个轻量级的微服务库,基于.Net 6 + Abp框架 可快速地将现有项目改造成为面向服务体系结构,实现模块间松耦合. 感谢 Rabbi ...

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

    转自:http://blog.csdn.net/congcong68/article/details/41113239 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架 ...

  5. zookeeper和淘宝dubbo的关系

    Dubbo建议使用Zookeeper作为服务的注册中心. 1.   Zookeeper的作用:         zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知 ...

  6. AWS EC2 CentOS release 6.5 部署zookeeper、kafka、dubbo

    AWS EC2 CentOS release 6.5 部署zookeeper.kafka.dubbo参考:http://blog.csdn.net/yizezhong/article/details/ ...

  7. 用ES6的class模仿Vue写一个双向绑定

    原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...

  8. Dubbo 是一个分布式服务框架

    Dubbo 是一个分布式服务框架-----http://www.cnblogs.com/chanshuyi/p/5144288.html

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

    序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...

随机推荐

  1. InnoDB的表类型,逻辑存储结构,物理存储结构

    表类型 对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键,如果在创建 ...

  2. P2P之UDP穿透NAT的原理与实现

    首先先介绍一些基本概念: NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用.NAT分为两 ...

  3. Eclipse插件手动安装

    拷贝至eclipse安装目录/dropins/文件夹下面: 不建议直接拷贝到features/ 和plugins/ 里面:

  4. 【Scala】Scala之Numbers

    一.前言 前面已经学习了Scala中的String,接着学习Scala的Numbers. 二.Numbers 在Scala中,所有的数字类型,如Byte,Char,Double,Float,Int,L ...

  5. SQL递归查询知多少

    最近工作中遇到了一个问题,需要根据保存的流程数据,构建流程图.数据库中保持的流程数据是树形结构的,表结构及数据如下图: 仔细观察表结构,会发现其树形结构的特点: FFIRSTNODE:标记是否为根节点 ...

  6. ubuntu-16.04(linux)使用Reaver爆破wifi密码(路由器的WPS功能漏洞)

    路由器的WPS功能 很多路由器都有WPS功能, 这边的WPS不是office工具软件, 而是路由器的一个功能: 路由器中WPS是由Wi-Fi联盟所推出的全新Wi-Fi安全防护设定(Wi-Fi Prot ...

  7. atom编辑器快捷键

    挑来挑去,还是决定选择atom,做为我的编程编辑器. 下面是我总结的atom快捷键 //1.atomcmd+,; 设置cmd+h; 隐藏程序cmd+alt+h; 隐藏其他程序 //2.文件cmd+n; ...

  8. 使用fullPage.js遇到的问题以及翻译

    使用fullPage.js做一简单页面,遇一古怪问题:.section中的h1标签始终被一插件生成的标签包裹,导致样式调整好不困难!花费数小时排查为何会生成这样一个标签,最终在fullPage.js的 ...

  9. removeAll

    问题:无法移除2个集合中相同元素 方法:移除所包含的其所有元素. 在执行removeAll方法时,会先对集合元素进行比较,如果元素相等才执行移除操作,说到这,相信很多人都已经明白是怎么回事了,因为不相 ...

  10. 睡不着,复习一下C++基础中的基础(深拷贝与浅拷贝)

    #include <iostream> #include <string> #include <assert.h> using namespace std; //声 ...