集群间如何实现session共享【面试+工作】

集群间如何实现session共享【面试+工作】

一、引言

针对企业,为了应对庞大的用户访问压力,目前大多数大型网站服务器都采用集群部署的方式;针对个人,仅一台服务器而言,也会安装多个tomcat进行错时更新,保证更新后台业务时服务不断开,即模拟了集群的运行方式。在此集群中,我们就不得不考虑一个用户鉴权的问题,即在不同服务上如何保证用户均已登录,并能获取相同的用户登录信息。

二、Java Web推荐的(公认的)用户鉴权机制

说此部分之前先了解几个概念: 1.请求,即Request,指客户端向服务器发送的信息,通常是通信的发起方; 2.响应,即Response,指服务器对请求的应答,通常是通信的回复方; 3.会话,即Session,服务器可将请求<->响应这一个完整的过程称为一次会话,并为这次会话生成一个唯一的标识符,即sessionId,用来表示这次会话,Session储存在服务器端; 4.Cookie,客户端保存在本地终端的数据,即Cookie储存在客户端。

Java Web的共用的用户鉴权机制是采用Session-Cookie技术,实现原理是:用户登录时,请求到达服务器,服务器调用通过getSession()方法判断session是否存在,如果不存在,则新建session,并通过其算法为session生成一个随机数作为sessionId,开发者可在session中储存一些用户信息;第二次请求时,如获取用户信息,getSession()方法判断session存在,则取出session,而不是新建,从而从session中获取到用户的相关信息。

客户端请求时,可以将cookie信息储存于request的head中发送给服务器; 服务器响应时,可以将cookie信息置于response中回传给客户端。 如下图代表,名称为test的cookie其值为aaa:

那么getSession()里究竟做了什么?

1.第一次用户请求,客户端本地没有任何数据,即其cookie为空,朝服务器发送request,getSession()中会解析request,发现其约定的cookie为null,则认为没有session,所以会重新创建一个session对象;

2.创建session后会将此session的id放入response中,回传给客户端,客户端则保存response中的cookie;

3.再次请求,服务器getSession()又会重新解析request获取cookie,发现了其中的sessionId,那么根据此sessionId去服务器的中去找,则得到了上次创建的session对象,那么则认为鉴权成功。

如此,便完成了鉴权的整个流程,Java逻辑代码(伪代码)如下:

如上,java中将sessionId在cookie中保存的名称叫做“JSESSIONID”,即“Java Session Id”之意,打开浏览器可以看到类型的信息,如图:

三、集群间如何实现session共享

按照前文所说的session-cookie机制,session是保存在每台服务器的,但在集群中,拥有多台服务器,每台各自为政,势必会造成在这台服务器中登录,获取session成功,但是到另一台服务器上,又会获取不到session,造成鉴权失败,这样对用户来说是极不友好的,那么怎么解决这个问题呢?

通过我们以上的分析,即可得出几种处理方式: A.找一块公共的空间用来储存session,而不是将session储存在集群节点的某台服务器上,此时,每一台服务器都能访问这块空间,从而实现session共享;

B.仍在每台服务器上保存session信息,不作修改,但采用另一种同步机制,实时同步没一台服务器的session信息;

C.构建一种全新的鉴权机制,不采用session-cookie机制,但要去除此鉴权机制对单个服务器的依赖。

综上所述,列举几种的具体实现方案:


1.持久化session到数据库,即使用数据库来储存session。数据库正好是我们普遍使用的公共储存空间,一举两得,推荐使用mysql数据库,轻量并且性能良好。

优点:就地取材,符合大多数人的思维,使用简单,不需要太多额外编码工作 缺点:对mysql性能要求较高,访问mysql需要从连接池中获取连接,又因为大部分请求均需要进行登录鉴权,所以操作数据库非常频繁,当用户量达到一定程度之后,极易造成数据库瓶颈,不适用于处理高并发的情况。


2.使用redis共享session。redis是一个key-value的储存系统。可以简单的将其理解为一个数据库,与传统数据库的区别是,它将数据储存于内存中,并自带有内存到硬盘的序列化策略,即按策略将内存中的数据同步到磁盘,避免数据丢失,是目前比较流行的解决方案。

优点:无需增加数据库的压力,因为数据存储于内存中,所以读取非常快,高性能,并能处理多种类型的数据。 缺点:额外增加一些编码,以便操作redis。


3.使用memcache同步session,memcache可以实现分布式,可将服务器中的内存组合起来,形成一个“内存池”,以此充当公共空间,保存session信息。

优点:数据储存在内存中,读取非常快,性能好; 缺点:memcache把内存分成很多种规格的存储块,有大有小,不能完全利用内存,会产生内存碎片,浪费资源,如果储存块不足,还会产生内存溢出。


4.通过脚本或守护进程在多台服务器之间同步session。

优点:实现了session共享; 缺点:对个人来说实现较为复杂,速度不稳定,有延时性,取决于现实中服务运行状态,偶然性较大,如果用于访问过快,可能出现session还没同步成功的情况。


5.使用NFS共享session。NFS是Network File Server共享服务器的简称,最早由Sun公司为解决Unix网络主机间的目录共享而研发。选择一台公共的NFS做共享服务器,储存所有session数据,每台服务器所需的session均从此处获取。

优点:较好的实现了session共享; 缺点:成本较高,对于个人来说难以实现。NFS依托于复杂的安全机制和文件系统,因此并发效率不高。


6.使用Cookie共享session。此方案可以说是独辟蹊径了,将分布式思想用到了极致。如上文分析所说,session-cookie机制中,session与cookie相互关联,以cookie做中转站,用来找到对应的session,其中session存放在服务器。那么如果将session中的内容存放在cookie中呢,那么则省略了服务器保存session的过程,后台只需要根据cookie中约定的标识进行鉴权校验即可。

优点:完美的贯彻分布式的理念,将每个用户都利用起来,无需耗费额外的服务器资源; 缺点:受http协议头长度限制,cookie中存储的信息不宜过多;为了保持cookie全局有效,所以其一般依赖在根域名下,所以基本上所有的http请求都需要传递cookie中的这些标记信息,所以会占用一些服务器的带宽;鉴权信息全存储于cookie中,cookie存在于客户端,服务器并没有储存相关信息,cookie存在着泄露的可能,或则其他人揣摩出规则后可以进行伪装,其安全性比其他方案差,故需要对cookie中信息进行加密解密,来增强其安全性。


在此,我们将选择方案2使用redis来具体实现集群下的session共享。

四、搭建测试环境

1.为模拟集群环境,需要两台服务器或在一台服务器上安装两个tomcat; 2.使用nginx做集群纷发; 3.安装redis充当公共的空间存储session; 4.框架中编写session储存业务,因为需要使用java操作redis,redis提供了驱动包jedis,故需要掌握jedis进行操作。

五、详细部署

5.1 安装多个tomcat 怎么安装tomcat此处不作说明,只说明安装额外的tomcat,本人原安装的tomcat目录为apache-tomcat-7.0.77

1.拷贝apache-tomcat-7.0.77为apache-tomcat-7.0.77_2 2.修改apache-tomcat-7.0.77_2下conf中server.xml文件端口号 ,共三处,将每处在原端口号port之上加1,确保两个tomcat不会共用端口,如下:

5.2 更改nginx配置,模拟集群 修改nginx配置文件nginx.conf文件,在server闭包外添加upstream,由上可知两个tomcat端口号分别为8080,8081

5.2 redis安装与配置

1.下载,官网:https://redis.io/download 2.安装,以4.0.1版本为例

3.启动

4.关闭

5.配置后台启动(redis默认是前台启动,启动成功后界面就持续停止在那个界面上,这对服务器操作很不方便)

如下图:

6.后台启动

如图:

7.关闭 杀掉redis进程,如图:

8.为redis配置系统服务,本人使用的系统是CentOS 7,需要配置使用systemctl进行管理。 /lib/systemd/system目录下创建文件redis.service,并编辑:

更多redis systemctl详细配置,看最后扩展

配置成功,启动完成后,通过服务可知其运行状态,如图:

至此,redis已全部安装部署完成。

六、编写代码实现功能

为了测试简便,后台web框架我选择的是JFinal,JFinal是中国开源社区中广受好评的后台轻量级极速web框架,因其操作简单,设计灵活而被大多数开发者所喜爱,有兴趣的朋友可以试试,用一次之后你就会喜欢它的。

这里用JFianl的另一个好处就是JFinal核心库中自带Redis插件,集成了jedis的各种使用方法,这样就不用自己去编写了,省了很大的代码量。Jedis基本操作:看最后扩展

为帮助理解代码,Jfinal中连接redis,只需要在主配置文件中编写:

redis存取数据:

正式代码如下,我们将会自定义session,每个sesison对象都是唯一的,需要给每个session分配一个唯一id,id生成算法,则可以借用UUID实现,UUID相关介绍:https://baike.baidu.com/item/UUID/5921266?fr=aladdin

自定义随机数工具类:

自定义RedisSession类,将替代原来的HttpSession:

仿造getSession()实现逻辑在控制器基类BaseController中自定义getSession()方法,获取RedisSession:

说明: 以上代码中,设想服务器给移动端和网页端同时提供服务,为了优化,但我希望移动端不需要频繁登录,就像微信一样,我将这个时间暂设一周;而网页端的话,session生存周期较短,只有半个小时,并且每次鉴权都刷新其可用时间,移动端只倒计时就可以了,一周登录一次就可以了。redis自带有过期策略,可以很好的实现这一点,同时为了保险起见,也手动验证了一下如过期,进行删除。为了避免初次请求时,多次调用getSession()生成多个session,故在创建session成功后记录其sessionId,再次调用getSession()时可对其进行验证。

七、结果测试

1.在Controller中编写两个接口,一为登录接口,登录成功,储存用户uid;二为验证登录接口,获取登录信息:

2.配置nginx分别跳转到不同tomcat下的不同接口

3.开启redis,nginx,两个tomcat下运行同样的项目,在浏览器中调用接口进行测试。

调用tomcat1的登录接口

日志:

调用tomcat2的登录接口

日志:

可以看到,两个tomcat中的信息完全一样,很好的达到了我们预计的效果。

到这里,本篇的内容也已经到了尾声,写的有点啰嗦,不过总算交代了来龙去脉,虽然有点累,但好歹写完了。未来还有很多工作要做,路漫漫其修远兮,吾将上下而求索。


扩展一:Java操作redis

在我们已安装Redis的基础之上(数据库测试环境Redis安装在 /opt/redis 中),将Redis添加到系统服务中去。

配置过程:

  • 进入/usr/lib/systemd/system/目录中,创建redis.service文件:
  • 文件创建好保存之后,要执行 systemctl daemon-reload 命令,使配置生效。
  • 开机启动: systemctl enable mongodb.service
  • 查看mongodb服务是否设置开机启动: systemctl is-enabled mongodb.service
  • 停止mongodb服务开机启动: systemctl disable mongodb.service
  • 启动: systemctl start mongodb.service
  • 查看状态: systemctl status mongodb.service
  • 重启: systemctl restart mongodb.service
  • 停止: systemctl stop mongodb.service

扩展二:Java操作redis

一、server端安装

1、下载

https://github.com/MSOpenTech/redis

可看到当前可下载版本:redis2.6

下载windows平台文件:

解压后,选择当前64位win7系统对应的版本:

2、安装

1)解压后将里面所有文件拷贝至redis安装目录:

几个exe程序的功能:    

redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询 (类似于 Apache 的ab 工具).

redis-check-aof.exe:更新日志检查

redis-check-dump.exe:本地数据库检查

redis-cli.exe:客户端

redis-server.exe:服务端

2)将路径添加至系统环境变量:过程根据操作系统配置(略)

3)cmd下启动redis-server

注:由于此处未指定配置文件,系统采用默认参数

3、下载对应的配置文件

由上面cmd输出可知,当前版本为2.6.12

原页面上打开所有发布版本,找到2.6.12:

下载zip文件:

拷贝出redis.conf配置文件至安装目录:


配置文件redis.conf 各字段含义:

daemonize yes #---默认值no,该参数用于定制redis服务是否以守护模式运行。---

pidfile /var/run/redis.pid #默认值/var/run/redis.pid,指定redis服务的进程号文件路径,以守护模式运行时需要配置本参数; port 6379 #默认值6379,指定redis服务的端口 # bind 127.0.0.1 #绑定ip,默认是本机所有网络设备; timeout 0 #客户端空闲n秒后断开连接;默认是 0 表示不断开。 loglevel notice ###设置服务端的日志级别,有下列几种选择: debug:记录详细信息,用于开发或调试; verbose:提供很多有用的信息,但是又不像debug那么详尽,默认就是这一选项; notice:适度提醒,多用于产品环境; warning:仅显示重要的警告信息; logfile "" ##指定日志的输出路径,默认值stdout,表示输出到屏幕,守护模式时则输出到/dev/null; 如果要输出日志到syslog中,可以启动syslog-enabled yes,默认该选项值为no。 # syslog-enabled no

databases 16 ###指定数据库的数量,默认为16个,默认使用的数据库是DB 0。

##########SNAPSHOTTING ############ ----以下为快照相关的设置:------ # save <seconds> <changes> ##指定多长时间刷新快照至磁盘,这个选项有两个属性值,只有当两个属性值均满足时才会触发;可以设置多种级别,例如默认的参数文件中就设置了: save 900 1:每900秒(15分钟)至少一次键值变更时被触发; save 300 10:每300秒(5分钟)至少10次键值变更时被触发; save 60 10000:每60秒至少10000次键值变更时被触发; save 900 1 save 300 10 save 60 10000 rdbcompression yes ##默认值yes,当dump数据库时使用LZF压缩字符串对象,如果CPU资源比较紧张,可以设置为no,选择不压缩; rdbchecksum yes # The filename where to dump the DB 数据库文件名 dbfilename dump.rdb ##默认值dump.rdb,dump到文件系统中的文件名 dir /usr/local/redis/db ##默认值./,即当前目录,dump出的数据文件的存储路径; ############ REPLICATION ################ ----以下为复制相关的设置,复制默认是不启用的,因此在默认的参数文件下列表参数均被注释---- # slaveof <masterip> <masterport> ##指定主端ip和端口,用于创建一个镜像服务 # masterauth <master-password> ##如果master配置了密码的话,此处也需做设置; slave-serve-stale-data yes ##默认值yes。当slave丢失与master端的连接,或者复制仍在处理,那么slave会有下列两种表现: 当本参数值为yes时,slave为继续响应客户端请求,尽管数据已不同步甚至没有数据(出现在初次同步的情况下); 当本参数值为no时,slave会返回"SYNC with master in progreee"的错误信息; slave-read-only yes ##默认从Redis是只读模式 # repl-ping-slave-period 10 ###默认值10,指定slave定期ping master的周期; # repl-timeout 60 ##默认值60,指定超时时间。注意本参数包括批量传输数据和ping响应的时间。 ############## SECURITY ############# ------以下为安全相关的设置------ # requirepass foobared ###指定一个密码,客户端连接时也需要通过密码才能成功连接; # rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 ###重定义命令,例如将CONFIG命令更名为一个很复杂的名字: # rename-command CONFIG "" 取消这个命令; #################LIMITS ################# -----以下为资源限制方面的设置------ # maxclients 10000 ##指定客户端的最大并发连接数,默认是没有限制,直到redis无法创建新的进程为止,设置该参数值为0也表示不限制,如果该参数指定了值,当并发连接达到指定值时,redis会关闭所有新连接,并返回'max number of clients reached'的错误信息; # maxmemory <bytes> ###设置redis最大可使用内存。当达到最大内存后,redis会尝试按照设置的回收策略删除键值。如果无法删除键值,或者保留策略设置为不清除,那么redis就会向发出内存的请求返回错误信息。当把redis做为一级LRU的缓存时本参数较为有用。 # maxmemory-policy volatile-lru ###默认值volatile-lru,指定清除策略,有下列几种方法: volatile-lru -> remove the key with an expire set using an LRU algorithm allkeys-lru -> remove any key accordingly to the LRU algorithm volatile-random -> remove a random key with an expire set allkeys->random -> remove a random key, any key volatile-ttl -> remove the key with the nearest expire time (minor TTL) noeviction -> don't expire at all, just return an error on write operations # maxmemory-samples 3 ###默认值3,LRU和最小TTL策略并非严谨的策略,而是大约估算的方式,因此可以选择取样值以便检查。 ################ APPEND ONLY MODE ############## -----以下为APPEND的配置---- ONLY模式的设置,默认情况下redis采用异步方式dump数据到磁盘上,极端情况下这可能会导致丢失部分数据(比如服务器突然宕机),如果数据比较重要,不希望丢失,可以启用直写的模式,这种模式下redis会将所有接收到的写操作同步到appendonly.aof文件中,该文件会在redis服务启动时在内存中重建所有数据。注意这种模式对性能影响非常之大。 appendonly no ##默认值no,指定是否启用直写模式; # appendfilename appendonly.aof ###直写模式的默认文件名appendonly.aof appendfsync:调用fsync()方式让操作系统写数据到磁盘上,数据同步方式,有下列几种模式: always:每次都调用,比如安全,但速度最慢; everysec:每秒同步,这也是默认方式; no:不调用fsync,由操作系统决定何时同步,比如快的模式; no-appendfsync-on-rewrite:默认值no。当AOF fsync策略设置为always或everysec,后台保存进程会执行大量的I/O操作。某些linux配置下redis可能会阻塞过多的fsync()调用。 auto-aof-rewrite-percentage:默认值100 auto-aof-rewrite-min-size:默认值64mb # appendfsync always appendfsync everysec # appendfsync no ################# ADVANCED CONFIG ################## -----以下为高级配置相关的设置---- hash-max-zipmap-entries:默认值512,当某个map的元素个数达到最大值,但是其中最大元素的长度没有达到设定阀值时,其HASH的编码采用一种特殊的方式(更有效利用内存)。本参数与下面的参数组合使用来设置这两项阀值。设置元素个数; hash-max-zipmap-value:默认值64,设置map中元素的值的最大长度;这两个 list-max-ziplist-entries:默认值512,与hash类似,满足条件的list数组也会采用特殊的方式以节省空间。 list-max-ziplist-value:默认值64 set-max-intset-entries:默认值512,当set类型中的数据都是数值类型,并且set中整型元素的数量不超过指定值时,使用特殊的编码方式。 zset-max-ziplist-entries:默认值128,与hash和list类似。 zset-max-ziplist-value:默认值64

activerehashing:默认值yes,用来控制是否自动重建hash。Active rehashing每100微秒使用1微秒cpu时间排序,以重组Redis的hash表。重建是通过一种lazy方式,写入hash表的操作越多,需要执行rehashing的步骤也越多,如果服务器当前空闲,那么rehashing操作会一直执行。如果对实时性要求较高,难以接受redis时不时出现的2微秒的延迟,则可以设置activerehashing为no,否则建议设置为yes,以节省内存空间。


ps:如果配置文件的版本和当前exe程序的版本不匹配,很容易

由于参数不一致导致server端无法启动。

4、通过指定的配置文件启动服务端

5、客户端访问测试

另起一个cmd窗口:

二、基本功能测试

1、程序基本结构

2、主要类

1)功能类

2)测试类

3、各个功能函数

1)key功能

运行结果:

2)String功能

运行结果:

3)List功能

运行结果:

4)Set功能

运行结果:

5)SortedSet功能(有序集合)

运行结果:

6)Hash功能

运行结果:


三、常用命令 1)连接操作命令 quit:关闭连接(connection) auth:简单密码认证 help cmd: 查看cmd帮助,例如:help quit 2)持久化 save:将数据同步保存到磁盘 bgsave:将数据异步保存到磁盘 lastsave:返回上次成功将数据保存到磁盘的Unix时戳 shundown:将数据同步保存到磁盘,然后关闭服务 3)远程服务控制 info:提供服务器的信息和统计 monitor:实时转储收到的请求 slaveof:改变复制策略设置 config:在运行时配置Redis服务器 4)对value操作的命令 exists(key):确认一个key是否存在 del(key):删除一个key type(key):返回值的类型 keys(pattern):返回满足给定pattern的所有key randomkey:随机返回key空间的一个 keyrename(oldname, newname):重命名key dbsize:返回当前数据库中key的数目 expire:设定一个key的活动时间(s) ttl:获得一个key的活动时间 select(index):按索引查询 move(key, dbindex):移动当前数据库中的key到dbindex数据库 flushdb:删除当前选择数据库中的所有key flushall:删除所有数据库中的所有key 5)String

set(key, value):给数据库中名称为key的string赋予值value get(key):返回数据库中名称为key的string的value getset(key, value):给名称为key的string赋予上一次的value mget(key1, key2,…, key N):返回库中多个string的value setnx(key, value):添加string,名称为key,值为value setex(key, time, value):向库中添加string,设定过期时间time mset(key N, value N):批量设置多个string的值 msetnx(key N, value N):如果所有名称为key i的string都不存在 incr(key):名称为key的string增1操作 incrby(key, integer):名称为key的string增加integer decr(key):名称为key的string减1操作 decrby(key, integer):名称为key的string减少integer append(key, value):名称为key的string的值附加value substr(key, start, end):返回名称为key的string的value的子串 6)List rpush(key, value):在名称为key的list尾添加一个值为value的元素 lpush(key, value):在名称为key的list头添加一个值为value的 元素 llen(key):返回名称为key的list的长度 lrange(key, start, end):返回名称为key的list中start至end之间的元素 ltrim(key, start, end):截取名称为key的list lindex(key, index):返回名称为key的list中index位置的元素 lset(key, index, value):给名称为key的list中index位置的元素赋值 lrem(key, count, value):删除count个key的list中值为value的元素 lpop(key):返回并删除名称为key的list中的首元素 rpop(key):返回并删除名称为key的list中的尾元素 blpop(key1, key2,… key N, timeout):lpop命令的block版本。 brpop(key1, key2,… key N, timeout):rpop的block版本。 rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

7)Set sadd(key, member):向名称为key的set中添加元素member srem(key, member) :删除名称为key的set中的元素member spop(key) :随机返回并删除名称为key的set中一个元素 smove(srckey, dstkey, member) :移到集合元素 scard(key) :返回名称为key的set的基数 sismember(key, member) :member是否是名称为key的set的元素 sinter(key1, key2,…key N) :求交集 sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合 sunion(key1, (keys)) :求并集 sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合 sdiff(key1, (keys)) :求差集 sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合 smembers(key) :返回名称为key的set的所有元素 srandmember(key) :随机返回名称为key的set的一个元素 8)Hash hset(key, field, value):向名称为key的hash中添加元素field hget(key, field):返回名称为key的hash中field对应的value hmget(key, (fields)):返回名称为key的hash中field i对应的value hmset(key, (fields)):向名称为key的hash中添加元素field hincrby(key, field, integer):将名称为key的hash中field的value增加integer hexists(key, field):名称为key的hash中是否存在键为field的域 hdel(key, field):删除名称为key的hash中键为field的域 hlen(key):返回名称为key的hash中元素个数 hkeys(key):返回名称为key的hash中所有键 hvals(key):返回名称为key的hash中所有键对应的value hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value


原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2018-04-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PhpZendo

PHP 文件系统完全指南

今天我们将开启一个新的探索旅程,深入到 PHP 文件系统中,系统的学习和掌握 PHP 文件系统的基本使用。

1843
来自专栏IT技术精选文摘

文件句柄与文件描述符

1.概述 在实际工作中会经常遇到一些bug,有些就需要用到文件句柄,文件描述符等概念,比如报错: too many open files, 如果你对相关知识一无...

5686
来自专栏北京马哥教育

注意!Python中的10个常见安全漏洞及修复方法

编写安全的代码很困难,当你学习一门编程语言、一个模块或框架时,你会学习其使用方法。在考虑安全性时,你需要考虑如何避免代码被滥用,Python也不例外,即使在标准...

1230
来自专栏一个会写诗的程序员的博客

Cookie 和 Session 机制原理分析 & 区别对比

Web application servers are generally "stateless":

1462
来自专栏SpiritLing

IIS进行URL重写——实现https重定向,文件类型隐藏访问重写,nodejs等服务重写等等

一、Why? 1、先来讲一讲为什么我们要使用url重写这个东西 2、因为我学习的后端是nodejs,然后我发现nodejs一个非常让人难受的事,就是它监听端口不...

8013
来自专栏用户2442861的专栏

redis 学习指南

http://www.cnblogs.com/hoojo/p/4466024.html

1991
来自专栏云计算教程系列

如何在Debian 9上使用mod_rewrite为Apache重写URL

Apache的mod_rewrite模块允许您以更干净的方式重写URL,将人类可读的路径转换为代码友好的查询字符串。它还允许您根据条件重写URL。

1634
来自专栏容器云生态

企业网站架构之Nginx+tomcat+memcached集群

nginx+tomcat+memcached应用 系统环境:RHEL6.4  x64   iptables -F   and selinux is disab...

3118
来自专栏北京马哥教育

Linux 中断处理浅析

最近在研究异步消息处理, 突然想起linux内核的中断处理, 里面由始至终都贯穿着”重要的事马上做, 不重要的事推后做”的异步处理思想. 于是整理一下~ ? 第...

5788
来自专栏跟着阿笨一起玩NET

asp.net中使用swfupload上传大文件

转载:http://www.cnblogs.com/niunan/archive/2012/01/12/2320705.html

1104

扫码关注云+社区

领取腾讯云代金券