Netty入门学习笔记(五)

十、Netty 核心源码剖析

基本说明

在这里插入图片描述

Netty 启动过程源码剖析

在这里插入图片描述
在这里插入图片描述
因为在IDEA中的netty包里没显示example包,所以需要找到maven下载的netty包,找到netty-all-4.1.20.Final-sources.jar文件,把后缀jar改为rar,然后解压,点进去就可以找到example包了。
我已经把源码的案例和老师的文档上传到了百度云,需要的可以自行下载:https://pan.baidu.com/s/1txMv9I8YYflztT19DYc7LA    密码: vdei
在这里插入图片描述

Netty 接受请求过程源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Pipeline Handler HandlerContext创建源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ChannelPipeline 调度 handler 的源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Netty 心跳(heartbeat)服务源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Netty 核心组件 EventLoop 源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

handler 中加入线程池和Context 中添加线程池的源码剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十一、用Netty 自己 实现 dubbo RPC

RPC基本介绍

在这里插入图片描述
在这里插入图片描述

RPC调用流程

RPC调用流程图

在这里插入图片描述

PRC调用流程说明

在这里插入图片描述

自己实现 dubbo RPC(基于Netty)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
publicinterface

//公共接口
public interface HelloService {

    //由服务提供者进行实现,为服务消费者提供服务
    String hello(String mes);
}

provider

public class HelloServiceImpl implements HelloService {

    private static int count = 0;

    //为消费者提供服务,当消费者调用此方法时,返回一个结果
    @Override
    public String hello(String mes) {
        System.out.println("收到客户端消息:" + mes);

        //根据mes返回不同的结果
        if(mes != null){
            return "服务器已收到消息【" + mes + "】" + (++count);
        }else{
            return "服务器已收到消息";
        }
    }
}
//启动服务的提供者(NettyServer)
public class ServerBootstrap {
    public static void main(String[] args) {
        NettyServer.startServer("127.0.0.1", 7000);
    }
}

netty

public class NettyClient {

    //创建线程池(数量:CPU核数)
    private static ExecutorService executor = Executors.newFixedThreadPool(
                                                Runtime.getRuntime().availableProcessors());
    private static NettyClientHandler client;
    private int count;

    //初始化客户端
    private static void initClient(){
        client = new NettyClientHandler();

        EventLoopGroup group = new NioEventLoopGroup();

        Bootstrap bootstrap = new Bootstrap()
                .group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)    //没有延时
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        //解码器
                        pipeline.addLast(new StringDecoder());
                        //编码器
                        pipeline.addLast(new StringEncoder());
                        //业务处理器
                        pipeline.addLast(client);
                    }
                });

        try {
            bootstrap.connect("127.0.0.1", 7000).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


    //代理模式获取代理对象
    public Object getBean(final Class<?> serviceClass, final String providerName){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[] {serviceClass}, (proxy, method, args) -> {

                    System.out.println("(proxy, method, args)进入..." + (++count));
                    if(client == null){
                        //初始化
                        initClient();
                    }

                    //设置要发给服务器端的信息
                    //providerName为协议头,args[0]客户端调用api hello(xxx) 的参数
                    client.setPara(providerName + args[0]);

                    return executor.submit(client).get();
                });
    }
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable {

    private ChannelHandlerContext context;  //上下文
    private String result;  //调用后返回的结果
    private String para;    //客户端调用方法时,传入的参数

    //设置参数 (2)
    void setPara(String para){
        System.out.println("setPara 被调用");
        this.para = para;
    }

    //与服务器连接成功后,就会被触发调用 (1)
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive 被调用");
        //因为在其他方法(call方法)里也要使用到ctx
        context = ctx;
    }

    //收到服务器回复的数据后,触发调用 (4)
    @Override
    public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead 被调用");
        //保存服务方返回的结果
        result = msg.toString();
        //唤醒等待的线程
        notify();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    //客户端真正发送数据的方法 (3) (5)
    //被代理对象调用,发送数据给服务器 -> 发送完后,wait -> 等待被唤醒(channelRead) -> 服务方返回结果
    //服务器回复结果会发送触发channelRead()方法,由这个方法来唤醒此线程
    @Override
    public synchronized Object call() throws Exception {
        System.out.println("call1 被调用");

        //发送数据给服务器端
        context.writeAndFlush(para);
        //进行wait,等待channelRead()方法获取到服务器回复的结果后唤醒
        wait();
        System.out.println("call2 被调用");
        //服务方返回的结果
        return result;
    }
}
public class NettyServer {

    //对外暴露
    public static void startServer(String hostname, int port){
        startServer0(hostname, port);
    }

    //NettyServer的初始化和启动
    private static void startServer0(String hostname, int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap()
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //解码器
                            pipeline.addLast(new StringDecoder());
                            //编码器
                            pipeline.addLast(new StringEncoder());
                            //业务处理器
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(hostname, port).sync();
            System.out.println("服务提供者启动成功,开始提供服务~");
            channelFuture.channel().closeFuture().sync();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //获取客户端发送的消息,并调用服务
        System.out.println("msg=" + msg);

        //客户端在调用服务器api时,需要遵循定义的协议
        //比如:每次发送的消息必须以某个字符串开头 "HelloService#hello#"
        if(msg.toString().startsWith("HelloService#hello#")){
            //截取内容并调用api
            String result = new HelloServiceImpl().hello(msg.toString().substring(
                    msg.toString().lastIndexOf("#") + 1));

            ctx.writeAndFlush(result);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

customer

public class ClientBootstrap {

    //定义协议头
    public static final String providerName = "HelloService#hello#";

    public static void main(String[] args) throws Exception {
        //创建一个消费者
        NettyClient customer = new NettyClient();

        //创建代理对象
        HelloService service = (HelloService) customer.getBean(HelloService.class, providerName);

        while (true){
            Thread.sleep(5 * 1000);
            //通过代理对象调用服务提供者的方法(服务)
            //每次调用时,HelloServiceImpl都会创建新对象
            String res = service.hello("你好,dubbo~");
            System.out.println("调用结果:" + res);
        }
    }
}

学习视频(p92-p116):https://www.bilibili.com/video/BV1DJ411m7NR?p=92

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值