• 2018/1/21 Netty通过解码处理器和编码处理器来发送接收POJO,Zookeeper深入学习


    package com.demo.netty;

    import org.junit.Before;
    import org.junit.Test;

    import io.netty.bootstrap.Bootstrap;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.serialization.ClassResolver;
    import io.netty.handler.codec.serialization.ClassResolvers;
    import io.netty.handler.codec.serialization.ObjectDecoder;
    import io.netty.handler.codec.serialization.ObjectEncoder;

    public class Client {
    private int port;
    @Before
    public void init() {
    this.port=8088;
    }
    @Test
    public void run() throws Exception {
    NioEventLoopGroup boosAndWorkerGroup = new NioEventLoopGroup();
    Bootstrap bootstrap = new Bootstrap();
    bootstrap.group(boosAndWorkerGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true)
    .handler(new ChannelInitializer<SocketChannel>() {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    //设置读取的字节大小为1kb也就是1024字节,同时禁止缓存类加载器
    ch.pipeline().addLast(new ObjectDecoder(1024,ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));
    ch.pipeline().addLast(new ObjectEncoder());
    ch.pipeline().addLast(new ClientHandler());

    }
    });
    ChannelFuture sync = bootstrap.connect("127.0.0.1", port).sync();
    sync.channel().closeFuture().sync();
    }

    }

    package com.demo.netty;

    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.util.ReferenceCountUtil;

    public class ClientHandler extends ChannelHandlerAdapter{

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    System.out.println(msg.toString());
    }
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    //连接服务器后自动发出
    Person person = new Person();
    person.setName("客户端");
    person.setAge(1);
    ctx.writeAndFlush(person);
    }
    }

    package com.demo.netty;

    import org.junit.Before;
    import org.junit.Test;

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelHandler;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.serialization.ClassResolver;
    import io.netty.handler.codec.serialization.ClassResolvers;
    import io.netty.handler.codec.serialization.ObjectDecoder;
    import io.netty.handler.codec.serialization.ObjectEncoder;

    public class Server {
    private int port;

    @Before
    public void init() {
    this.port = 8088;
    }

    @Test
    public void run() throws Exception {
    NioEventLoopGroup boosGroup = new NioEventLoopGroup();
    NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    serverBootstrap.group(boosGroup, workerGroup).channel(NioServerSocketChannel.class)
    .option(ChannelOption.SO_BACKLOG, 1024).option(ChannelOption.SO_SNDBUF, 1024).option(ChannelOption.SO_RCVBUF, 1024).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    //发送pojo一定要调用解码处理器再调用编码处理器,这里编码处理器的参数的意思是,接收1m大小的字节,同时对类加载器进行缓存,当虚拟机缓存不足时,会自动释放缓存,为了防止异常码流和解码错位而导致的内存溢出
    ch.pipeline().addLast(new ObjectDecoder(1024*1024,ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
    ch.pipeline().addLast(new ObjectEncoder());
    ch.pipeline().addLast(new ServerHandler());
    }
    });
    ChannelFuture sync = serverBootstrap.bind(port).sync();
    //对Server端进行阻塞,等待服务端监听端口关闭后,主线程才退出
    sync.channel().closeFuture().sync();
    }
    }

    package com.demo.netty;

    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;

    public class ServerHandler extends ChannelHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    Person per = (Person)msg;
    System.out.println(per.toString());
    Person person = new Person();
    person.setName("服务端");
    person.setAge(1);
    ctx.writeAndFlush(person);
    }
    }

    Zookeeper是一个开源的集群管理服务,虽然它本质上只提供两个功能,存储客户端发来的数据并将其以树形结构进行存储,还有对保存数据节点的监听,但是我们可以靠代码设计来通过这两个
    功能来解决一系列的问题;
    Zookeeper典型应用场景:
    配置管理
    集群管理
    发布与订阅
    数据库切换
    分布式日志的收集
    分布式锁,队列管理等等

    Zookeeper数据类型与结构:
    Zookeeper的所存储的数据结构我们成为Znode,它是通过路劲进行引用也就是/开头,顶层节点就是/,并且它兼具文件和目录两种特点,既可以保存数据,源信息,ACL,时间戳等数据结构,
    又像目录一样可以作为路劲标识的一部分,每一个节点都是Znode,每个持久节点都可以拥有子节点(临时节点不能拥有),Znode由三个部分组成:
    stat:此为状态信息描述该Znode的版本,权限等信息;
    data:与该Znode关联的数据;
    children:该节点下的子节点;
    Zookeeper本质上数据类型只有两种,持久节点和临时节点,但因为它们都各自有另一种生成方式,也就是带有序列号的持久节点和临时节点,所以变成了4种(序列号的生成由
    Zookeeper根据保存数据时事务成功时的顺序进行递增),同时每个节点又因为保存着版本号而拥有着不同的数据;

    Zookeeper集群选举原理
    Zookeeper集群分为三种角色,主(Leader),从(follower),obServer(Learner,很少用到,就是复制客户端的数据,只负责读,不需要leader主动分发任务,并且也不参与选举)
    首先,要组成Zookeeper必须要三台或以上的服务器,第一台开机后,首先给自己投票,之后判断是否有其它机器,没有就进入Looking状态,如果有就发给其它服务器反馈信息让它们给自己投票;
    第二台同理,只有到第三台的时候,才会使用选举算法根据服务器ID,越大投票分量越重(也就是我们在创建集群是,在zookeeper保存数据的地方新建一个myid的文件并存储值(这个值根据你搭建集群时给每个服务定的值,具体百度Zookeeper集群搭建)),
    逻辑时钟(指的时每台服务器投票的次数),每台服务器都会把自己的ID和逻辑时钟的保存的次数发给其它服务器,其实还有关于服务器中保存数据的版本信息之类,不过这个占用的投票权利不大;之后一旦选举出leader,就算后面新增的服务器,
    它的ID再怎么大,都只能是follower;
    选举完成后由Leader来分发并且也只能由Leader任务给其它Follower,就算客户端是把保存数据的请求发送给了Follower,Follower也会转发给Leader,之后由Leader先保存这个数据,然后分派任务,让其它Follower也全部保存这个数据,
    这样就保证了数据的一致性,当有大于一般数量的集群服务器保存了这个数据后,Leader就会返回消息给客户端,告知其保存成功;Zookeeper增删改都是原子性的,也就是说,只要你修改了某个节点中保存的数据,那么相应的,这条数据的版本信息,源信息都会被做相应处理;
    同时Zookeeper是有事物支撑的;

  • 相关阅读:
    如何区分 PaaS、IaaS 、SaaS?
    IP黑名单
    VMware vSphere 6 序列号
    什么是DMZ区域,DMZ区域的作用与原理
    PM2 进程管理工具
    解决Centos6 2021年后yum失效问题
    解决: Got permission denied while trying to connect to the Docker daemon socket
    Windows原版镜像
    使用LemonBench工具对Linux服务器进行综合评测
    使用 Packet Sender 发送TCP包
  • 原文地址:https://www.cnblogs.com/yangfeiORfeiyang/p/8325757.html
Copyright © 2020-2023  润新知