网络通信之Session的历史血脉

Session经常被大家翻译为【会话】,在一个应用内部设计架构中,它通常指进程内保存的状态数据或者属性。

2007年

2007年我的本科毕业设计里,用了很多JSP里嵌Java代码的操作。比如登录是这么写的:

0bd47446ee40fbccb46f2492991a6209.png

运行效果是这样的:

2cff6df1c962fb51654b34db7c81a4bc.png

对的,我就是用这么原始的技术成功的混到了毕业文凭。

我周围的男同学技术比我要好一些,他们的用法也比我要高级,前端JSP里没有调用Java代码,有专门的后端来处理。

HttpSession hs = request.getSession();
PrintWriter pw = response.getWriter();
String msg = request.getParameter("ming");
pw.println(msg);
pw.println(hs.getId());

这两种方式本质上就是使用Java Servlet配合http协议标准来实现的。

HttpSession

服务器会为每一个用户 创建一个独立的HttpSession

原理

当用户第一次访问Servlet时,服务器端会给用户创建一个独立的Session

并且生成一个SessionID,这个SessionID在响应浏览器的时候会被装进cookie中,从而被保存到浏览器中

当用户再一次访问Servlet时,请求中会携带着cookie中的SessionID去访问

对于Servlet而言。服务器会根据这个SessionID去查看是否有对应的Session对象,有就拿出来使用;没有就创建一个Session(相当于用户第一次访问)。换句话说:若Servlet是客户端访问的第一个WEB应用的资源,则只有调用了request.getSession()或request.getSession(true) 才会创建HttpSession对象。

域的范围

    Context域 > Session域 > Request域

    Session域 只要会话不结束就会存在 但是Session有默认的存活时间(30分钟)

注意点

1>这时候的Session是跨线程的。

2>一个Session的概念需要包括特定的客户端,特定的服务器端以及不中断的操作时间。A用户和C服务器建立连接时所处的Session同B用户和C服务器建立连接时所处的Session是两个不同的Session。基于这个注意点,多数线上服务都是采用集群或者在扩展性上支持了集群,所以现在基本上没有人使用HttpSession了,当然只是做个毕设还是可以的。

总结

通过HttpSession主要是获取其中保存的状态数据或者属性,是一种状态的保持。

2015年

2015年我做了一个PHP的项目,发现在PHP里Session那个好用。其实PHP里的Session和Java Servlet的Session原理基本相同。在集群情况下也是会失效的。但是为什么都过去8年了,Java中基本已经淘汰了这种用法,在PHP里还在用呢?

我个人理解那就是PHP语言的本身适用范围了。PHP本身适用于简单轻量的小型系统,这种系统有些就是单服务器在运行的。对可用性要求也不是特别高,出了问题可以通过立即重启或者启用备份服务器解决。Session里的信息如用户信息丢了用户重新登录就好了。

总结

通过PHP里Session和HttpSession一样,主要是获取其中保存的状态数据或者属性,是一种状态的保持。

2016年

当时做项目用到ActiveMQ,它实现了JMS标准。先看一段简单代码:

public class JMSProducer {
    public static void main(String[] args) {
        //连接工厂
        ConnectionFactory connectionFactory;
        //连接
        Connection connection  = null;
        //会话,接受或者发送消息的线程
        Session session;
        //消息的目的地
        Destination destination;
        //消息生产者
        MessageProducer messageProducer;
        //实例化工厂
        connectionFactory = new ActiveMQConnectionFactory(ConnectionConstants.BROKENURL);
        try {
            //获取连接
            connection = connectionFactory.createConnection(ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
            //启动连接
            connection.start();
            //创建session
            //参数1:1、true:支持事务
            //为true时:paramB的值忽略, acknowledgment mode被jms服务器设置为SESSION_TRANSACTED 。  
            // 2、false:不支持事务 
            // 为false时:paramB的值可为Session.AUTO_ACKNOWLEDGE、Session.CLIENT_ACKNOWLEDGE、DUPS_OK_ACKNOWLEDGE其中一个,
            // 为Session.SESSION_TRANSACTED时会报错!
            //参数2:Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。异常也会确认消息,应该是在执行之前确认的
            //Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。可以在失败的
            //时候不确认消息,不确认的话不会移出队列,一直存在,下次启动继续接受。接收消息的连接不断开,其他的消费者也不会接受(正常情况下队列模式不存在其他消费者)
            //DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效。
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            //创建一个消息队列
            destination = session.createQueue("firstDemo");
            //创建消息生成这
            messageProducer = session.createProducer(destination);
            //创建消息
            TextMessage message = session.createTextMessage("ACTIVEMQ 生产者 生产消息,这是第"+i+"次生产");
            //发出消息
            messageProducer.send(message);


            session.commit();
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

注意在上面的connection连接中创建了session。在《深入理解MQ生产端的底层通信过程-理解channel》MQ中怎么使用Channel那一节,RabbitMQ的生产端 connection.createChannel()。对比之下,情不自禁就要问了,这里的Channel等价于Session?

自然不是啦,针对他们的区别。知乎上有个神回复:“Session是会话,比如打电话,从拨号到挂断这就是一个Session;Channel是通道,我的理解是比如打电话时,Channel表示是使用联通信号或者是移动信号或者是电信信号。”

Channel是文件的读取等操作的抽象,而Session我理解是连接中状态数据的保持或者复用。Channel在《深入理解MQ生产端的底层通信过程-理解channel》里讲过了。那Session这块怎么理解呢?

在上面JMSProducer的代码中,我可写了大段的注释。这些注释可不是白写的。我们列举一下在上面的Session中显式的保存了哪些东西:

  • 是否支持事务

  • 客户端收到消息是否自动确认

  • 一个消息队列firstDemo

  • 一个可以发消息给firstDemo的生产者

  • 一个消息内容

一般我们每次发消息时,消息内容会需要新建,但是生产者、消息队列、是否支持事务和客户端收到消息是否自动确认这些都可以复用。幸好人家设计的时候也设计了Session,每次直接用就可以了。

总结:MQ中的Session是连接中状态数据的保持或者复用

2020年

项目原因我研究了mybatis的源码,本来都计划为了满足项目需求自己重写一个mybatis了,后来重新规划设计没有做。在《mybatis的本质和原理》里我手撕了一个简易mybatis,里面有提到SqlSession。作用类似于一个 JDBC 中的 Connection 对象的代理,代表着一个连接资源的启用,它的作用有 3 个:

  • 获取 Mapper 接口。

  • 发送 SQL 给数据库。

  • 控制数据库事务。

本质上我理解也是连接中状态数据的保持或者复用。一段代码感受一下:

//定义 SqlSession
SqlSession sqlSession = null;
try {
    // 打开 SqlSession 会话
    sqlSession = SqlSessionFactory.openSession();
    // some code...
    sqlSession.commit();    // 提交事务
} catch (IOException e) {
    sqlSession.rollback();  // 回滚事务
}finally{
    // 在 finally 语句中确保资源被顺利关闭
    if(sqlSession != null){
        sqlSession.close();
    }
}

上面在sqlSession对象中进行了事务的提交和回滚操作,非常类似于咱们在navicate等mysql客户端界面上的一个会话终端的操作。

在这同一个session下,因为就好像之前在HttpSession 登录有效期内用户的操作一样,只是界面不同。

总结

本文从个人的时间经历,分析了Session演进的血缘关系。这十几年的演进中,Session的概念越来越泛化,但是本质上还是保存的状态数据或者属性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值