- 浏览: 160255 次
- 性别:
- 来自: 奥克兰
-
文章分类
最新评论
-
u012625419:
...
CXF之用spring配置服务端和客户端实例(转) -
bambooshangye:
CXF之用spring配置服务端和客户端实例(转) -
最佳蜗牛:
写的很好,谢谢!
tomcat下的server.xml文件和context.xml (转) -
mohaowen1989:
亲 有中文版的么?在grails基础上的spring-secu ...
Simplified Spring Security with Grails(转) -
douhongyang:
挺好,,思路很清晰,
spring security详解教程 (转)
原文转自http://snowolf.iteye.com/blog/743611
Apache
和 Tomcat
原本就是一家,更是一家亲!Apache与Tomcat整合,无非是将Apache作为前端根据请求路径、端口、代理分发给多个Tomcat,以到达转发
和负载均衡
的目的!同时,通过Apache和Tomcat相互作用,进行粘性会话
,会话拷贝
构建集群
!这一切的最终结果就是“云服务
”!不要说Session
不重要,当下火爆的团购
,如果离开Session
还能快活多久?如何保证Session同步
,仍然是不能回避的问题!
这里要说的是基于HTTP和AJP跳转方式的负载均衡实现,关于JK,由于效率问题一直成为诟病,这里就不折腾它的复杂配置了!
至于说Apache+Tomcat+SSL,并不是难题!只要完成了Apache+SSL然后配置相应的负载均衡、反向代理等等就可以达到目的,相关Apache+SSL参考征服 Apache + SSL
Ubuntu Server 10.04版本,Apache选用2.2.14,Tomcat选用6.0.24。
相关内容:
征服 Apache + SSL
征服 Apache + SVN
征服 Apache + Tomcat
步骤:
- 安装Apache基本模块
- 后台监控
- 负载均衡简单测试
- 配置Tomcat相关模块(AJP)
- 保持Session唯一,粘性会话
- Tomcat集群,Session复制
1.安装Apache相关模块
负载均衡需要的主要是代理模块!
经过几次Apache配置尝试,在Ubuntu下配置Apache实在是太容易了。加载什么模块、取消什么模块两个命令搞定。
- #启用模块
- sudo a2enmod <model>
- #禁用模块
- sudo a2dismod <model>
#启用模块 sudo a2enmod <model> #禁用模块 sudo a2dismod <model>
这里,我们需要让Apache提供代理服务,其中又包含基于http、ftp、ajp等等协议的代理功能,同时还需要负载均衡模块。我们可以通过命令逐个加载:
- #代理核心模块
- sudo a2enmod proxy
- #代理AJP模块
- sudo a2enmod proxy_ajp
- #代理负载均衡模块
- sudo a2enmod proxy_balancer
- #代理HTTP模块
- sudo a2enmod proxy_http
- #代理FTP模块
- sudo a2enmod proxy_ftp
#代理核心模块 sudo a2enmod proxy #代理AJP模块 sudo a2enmod proxy_ajp #代理负载均衡模块 sudo a2enmod proxy_balancer #代理HTTP模块 sudo a2enmod proxy_http #代理FTP模块 sudo a2enmod proxy_ftp
完成上述操作后,系统会提示重启Apache!
先不着急重启,现学现卖,了解下Apache的目录结构。在Ubuntu下配置Apache主要是在/etc/apache2
目录下:
分述:
- apache2.conf 核心配置文件,一般不需要修改!
- conf.d 目录,里面包含了一些字符集设置,文档等设置!
- dav_svn.authz 和dav_svn.passwd 是前面做SVN时,相关权限、密码文件。
- envvars 定义了运行时的用户身份——www-data。
- httpd.conf 是Apache留给我们自己折腾的配置文件,默认为空。apache2.conf 会加载这个文件。
- ports.conf 端口默认配置。apache2.conf 会加载这个文件。
- magic 为mod_mime_magic模块服务。
- mods-enabled 和mods-available mods-enabled 会被apache2.conf 加载,里面包含*.load和*.conf文件。*.load文件中是加载相应的模块(位于/usr/lib/apache2/modules/ 中),而*.conf中是对应的基本配置。但这些文件其实都是链接到mods-available 中相应的文件上。当我们通过a2enmod 操作时,实际上正是操作了这些软链接。
- sites-available 和sites-enabled 与 mods-enabled 和mods-available 的关系类似,只是其中包含的是站点内容。
罗嗦了一堆,下面配置负载均衡部分。
执行修改:
- sudo vi /etc/apache2/mods-available/proxy.conf
sudo vi /etc/apache2/mods-available/proxy.conf
上图红框中的内容是原始内容,白框中的内容是我新加的部分。
注意红框中的配置:
- <Proxy *>
- AddDefaultCharset off
- Order deny,allow
- #Deny from all
- Allow from localhost ip6-localhost
- </Proxy>
<Proxy *> AddDefaultCharset off Order deny,allow #Deny from all Allow from localhost ip6-localhost </Proxy>
在默认配置中,Deny from all
处于可用状态。当我们配置其他代理节点时,将导致杜绝访问!
使用Allow from localhost ip6-localhost
限制仅允许本机访问!
再说,白框中的内容:
- <Proxy balancer://zlex>
- BalancerMember http://localhost:8080 /
- BalancerMember http://192.168 . 49.1 : 8080 /
- </Proxy>
<Proxy balancer://zlex> BalancerMember http://localhost:8080/ BalancerMember http://192.168.49.1:8080/ </Proxy>
这里,我配置了一个负载均衡节点balancer://zlex
,其中包含了两个服务http://localhost:8080/
和http://192.168.49.1:8080/
,一个是虚拟机上的Tomcat、一个是真机上的Tomcat。这里使用的Http的转发方式,当然,使用AJP未尝不可,稍后详述!
这里的节点次序会有一个先后关系,Apache会将请求按照FIFO的方式调度顺次分配到各个节点上!如果其中有一个节点挂掉,将跳过该节点顺次寻找可用节点。
再说代理和反向代理:
- ProxyPass /zlex balancer://zlex
- ProxyPassReverse /zlex balancer://zlex
ProxyPass /zlex balancer://zlex ProxyPassReverse /zlex balancer://zlex
这里配置,如果要访问/zlex
路径时,将跳转到balancer://zlex
上,也就是享受负载均衡!
2.后台监控
我们如何知道某个节点负载多少,响应时间多久,服务是否正常呢?Apache提供了负载均衡监控平台:http://localhost/balancer-manager
。但是,这个服务默认是不存在。
除了用于负载均衡配置、监控的balancer-manager
还有http://localhost/server-status
和http://localhost/server-info
我们需要添加info模块:
- #系统信息模块
- sudo a2enmod info
#系统信息模块 sudo a2enmod info
同时,为了能够使用balancer-manager
,我们需要配置:
- <Location /balancer-manager>
- SetHandler balancer-manager
- Order Deny,Allow
- #Deny from all
- Allow from localhost ip6-localhost
- </Location>
<Location /balancer-manager> SetHandler balancer-manager Order Deny,Allow #Deny from all Allow from localhost ip6-localhost </Location>
把这段代码放到哪?由于它同属系统信息配置,我把它放到了info.conf
中,说白了就是照猫画虎:
- sudo vi /etc/apache2/mods-available/info.conf
sudo vi /etc/apache2/mods-available/info.conf
注意,这段代码放到了<IfModule mod_info.c>
和</IfModule>
之间!
现在,我们重启Apache:
- sudo /etc/init.d/apache2 restart
sudo /etc/init.d/apache2 restart
来看看管理界面http://localhost/balancer-manager
:
我们再来看看服务器基本信息http://localhost/server-info
:
上述两个服务需要加载info模块,而服务器状态(server-status)不需要http://localhost/server-status
:
3.负载均衡简单测试
疯狂访问http://localhost/zlex
,直到手酸眼烦!
我这里故意使用不同了Tomcat界面,来验证自己的配置是否生效。更疯狂的是,我甚至把节点指向了百度、搜狐,来测试负载均衡的效果。如果你细致观察,Apache是将请求顺次分配到各个节点上的。
如果其中一个节点发生问题(例如,强行关闭一个Tomcat,或配置一个错误节点)Apache将会经过几次尝试后,绕过这个问题节点,寻找可以成功访问的节点。如果这个节点恢复正常使用,Apache将在该Tomcat恢复正常工作后大约1分钟内将该节点标识为可用!
现在,再看看现在的后台(http://localhost/balancer-manager
)啥样子:
如果我们控制一个节点的状态是否可用,该怎么做:
涉及到负载量,session同步等等,我们最后讨论!
4.配置Tomcat相关模块(AJP)
基于Http协议分发并不复杂,但AJP效果更好!一次诡异事件中,内网访问正常,外网访问多次失败,最后通过AJP方式完美解决了!
在Tomcat中配置AJP也很简单,修改server.xml
开启AJP模块:
- sudo vi /etc/tomcat6/server.xml
sudo vi /etc/tomcat6/server.xml
开启AJP配置:
- < Connector port = "8009" protocol = "AJP/1.3"
- URIEncoding = "UTF-8"
- redirectPort = "8443" />
<Connector port="8009" protocol="AJP/1.3" URIEncoding="UTF-8" redirectPort="8443" />
注意使用的端口port="8009"
,字符集URIEncoding="UTF-8"
,这是输入框、请求字符集乱码的入口!
接下里就可以通过AJP方式进行节点分发了。修改/etc/apache2/mods-available/proxy.conf
:
- sudo vi /etc/apache2/mods-available/proxy.conf
sudo vi /etc/apache2/mods-available/proxy.conf
将http
改为ajp
,将8080
改为8009
:
- <Proxy balancer://zlex>
- BalancerMember ajp://localhost:8009 /
- BalancerMember ajp://192.168 . 49.1 : 8009 /
- </Proxy>
<Proxy balancer://zlex> BalancerMember ajp://localhost:8009/ BalancerMember ajp://192.168.49.1:8009/ </Proxy>
重启Apache:
- sudo /etc/init.d/apache2 restart
sudo /etc/init.d/apache2 restart
再看看管理界面http://localhost/balancer-manager
至此,我们完成了基本负载均衡的基本配置!
/etc/apache2/mods-available/proxy.conf
还有一些属性,比如noFailOver
是否打开失败转移,On
|Off
,默认为Off,添加在ProxyPass
后面,如:
- ProxyPass /zlex balancer://zlex stickySession=JSESSIONID noFailOver=On
ProxyPass /zlex balancer://zlex stickySession=JSESSIONID noFailOver=On
如果这样配置,当提供给你服务的服务器发生异常,那么你将一直看着它返回给你503,直到系统恢复正常!
5.Session唯一,粘性会话
Apache已经可以轻松将内容处理的工作分配给各个Tomcat了!
当然,这还不够,Session还是个问题!
WHY?
我们来做一系列修改,来检测Session到底出现了什么问题!
先来改造Tomcat,修改server.xml
:
- sudo vi /etc/tomcat6/server.xml
sudo vi /etc/tomcat6/server.xml
修改<Engine />
节点,增加jvmRoute
属性:
- < Engine
- name = "Catalina"
- defaultHost = "localhost"
- jvmRoute = "tomcat1" >
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
另一个Tomcat设置改为
- < Engine
- name = "Catalina"
- defaultHost = "localhost"
- jvmRoute = "tomcat2" >
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">
通过jvmRoute
,指定了Tomcat唯一标识!
然后修改/etc/apache2/mods-available/proxy.conf
- sudo vi /etc/apache2/mods-available/proxy.conf
sudo vi /etc/apache2/mods-available/proxy.conf
如下:
- <Proxy balancer: //zlex>
- BalancerMember ajp://localhost:8009/zlex route=tomcat1
- BalancerMember ajp://192.168.49.1:8009/zlex route=tomcat2
- </Proxy>
- ProxyPass /zlex balancer://zlex
- ProxyPassReverse /zlex balancer://zlex
<Proxy balancer://zlex> BalancerMember ajp://localhost:8009/zlex route=tomcat1 BalancerMember ajp://192.168.49.1:8009/zlex route=tomcat2 </Proxy> ProxyPass /zlex balancer://zlex ProxyPassReverse /zlex balancer://zlex
这里需要通过修改route
属性,将Apache与Tomcat关联起来!
注意,Tomcat中定义的jvmRoute
需要与Apache定义的route
相对应!
我们来看一下http://localhost/balancer-manager
发生了什么变化:
我们注意到route字段有了新的标识,当然,我们也可以通过这个配置界面修改这些信息,但当前修改不会真的修改/etc/apache2/mods-available/proxy.conf文件,Apache重启后将丢失。
为了更细致的对比进过复杂均衡的结果,这里增加了zlex应用!主要是监控Session的变化!
只看核心代码:
- <b>当前SessionID:</b>
- <br />
- <%
- String sessionID = session.getId();
- out.println(sessionID);
- System.err.println("sessionID = " + sessionID);
- // 如果有新的 Session 属性设置
- String dataName = request.getParameter("dataName" );
- if (dataName != null && !dataName.isEmpty()) {
- String dataValue = request.getParameter("dataValue" );
- session.setAttribute(dataName, dataValue);
- }
- %>
- <br />
- <br />
- <b>Session属性列表:</b>
- <br />
- <%
- Enumeration<String> e = (Enumeration<String>) session
- .getAttributeNames();
- while (e.hasMoreElements()) {
- String name = e.nextElement();
- String value = (String) session.getAttribute(name);
- out.println(name + " = " + value + "<br>" );
- System.err.println(name + " = " + value);
- }
- %>
- <form method="POST" >
- <ul style="list-style-type: none;" >
- <li><label for="dataName" >键:</label><input size= "20" id= "dataName"
- name="dataName" ></li>
- <li><label for="dataValue" >值:</label><input size= "20"
- id="dataValue" name= "dataValue" ></li>
- <li><input type="submit" value= "提交" /></li>
- </ul>
- </form>
<b>当前SessionID:</b> <br /> <% String sessionID = session.getId(); out.println(sessionID); System.err.println("sessionID = " + sessionID); // 如果有新的 Session 属性设置 String dataName = request.getParameter("dataName"); if (dataName != null && !dataName.isEmpty()) { String dataValue = request.getParameter("dataValue"); session.setAttribute(dataName, dataValue); } %> <br /> <br /> <b>Session属性列表:</b> <br /> <% Enumeration<String> e = (Enumeration<String>) session .getAttributeNames(); while (e.hasMoreElements()) { String name = e.nextElement(); String value = (String) session.getAttribute(name); out.println(name + " = " + value + "<br>"); System.err.println(name + " = " + value); } %> <form method="POST"> <ul style="list-style-type: none;"> <li><label for="dataName">键:</label><input size="20" id="dataName" name="dataName"></li> <li><label for="dataValue">值:</label><input size="20" id="dataValue" name="dataValue"></li> <li><input type="submit" value="提交" /></li> </ul> </form>
将其做成一个名为zlex的web应用,分别部署到两个Tomcat上!
然后重启Apache:
- sudo /etc/init.d/apache2 restart
sudo /etc/init.d/apache2 restart
不断刷新http://localhost/zlex
,看看真正的恶魔:
第1次:
第2次:
第3次:
第4次:
仔细观察,每次请求都按照负载均衡配置的节点次序依次请求到不同的Tomcat上。尤其是当我们通过jvmRoute
和route
做了绑定之后,信息更加准确。但是,仔细观察,每次请求的SessionID都是不一样!
对于纯Web应用,尤其是依靠SessionID区分唯一用户的应用,这将是一场噩梦——解决了服务器压力均衡问题,却带来了SessionID不唯一问题!这就需要SessionID绑定,或者说叫做“会话复制”。
如果这时候你在页面上提交表单,将键值对保持在session中,在页面刷新后,将无法获得该信息,因为Seesion丢失了!
接着修改/etc/apache2/mods-available/proxy.conf
,让SeesionID保持唯一:
- sudo vi /etc/apache2/mods-available/proxy.conf
sudo vi /etc/apache2/mods-available/proxy.conf
增加stickySession
属性:
- ProxyPass /zlex balancer://zlex stickySession=JSESSIONID
ProxyPass /zlex balancer://zlex stickySession=JSESSIONID
stickySession
粘性会话,根据这一属性,浏览器将通过cookie绑定SeesionID。如果这个时候再次访问http://localhost/zlex
,你会发现,页面不会来回跳转了!
sticky是什么?
利用负载均衡器的sticky模式的方式把所有同一session的请求都发送到相同的Tomcat节点。这样不同用户的请求就被平均分配到集群 中各个tomcat节点上,实现负载均衡的能力。这样做的缺点是没有灾难恢复的能力。一旦一个节点发生故障,这个节点上所有的session信息全部丢 失;
同一用户同一session只和一个webServer交互,一旦这个webserver发生故障,本次session将丢失,用户不能继续使用 !
提交一个Session设定看看http://localhost/zlex
:
观察后台日志:
再看看返回页面,这相当于一次页面刷新,如果正常粘性会话,我们将获得当前SessionID对应的一切信息:
这说明粘性会话生效了!
我们得到了形如
的SessionID。这样,我们就能知道当前访问的是哪台服务器了!
如果,换一个浏览器打开该页面http://localhost/zlex
,将会获得一个新的SessionID,并且,根据Apache中配置的负载均衡节点列表依次访问下一个节点!
如果这时候负载均衡节点列表中某一节点发生异常,那么Apache将按照惯例,跳转该节点,并在该节点恢复正常后约1分钟内重新将其纳入可用节点!
修改刚才的jsp页面,看看Http头中都有些什么:
- <b>Cookie信息:</b>
- <br />
- ${header["cookie" ]}
- <br />
- <b>Host信息:</b>
- <br />
- ${header["host" ]}
- <br />
<b>Cookie信息:</b> <br /> ${header["cookie"]} <br /> <b>Host信息:</b> <br /> ${header["host"]} <br />
sticky模式
的根本在于浏览器支持cookie,如果浏览器不支持cookie,则需要修改server.xml文件中的<Context />节点,将cookie
置为false
,关闭cookie功能,让jsessionid显式传递!
6.Tomcat集群,Session复制
经过两天反复研究,两只互不相认的Tomcat终于在网络上“资源共享”了——Session复制成功!
关于Tomcat集群以及Session复制
,网上已经有很多很多,但是否真的能用?!为了确认这一问题,周末还跑到书店翻了翻《Apache Tomcat 高级编程》,参考Clustering/Session Replication HOW-TO
(有点小错误),经过两天苦战,克服种种小问题,终于拿下!
如果其中一台服务器发生故障,根据负载均衡的原理,Apache会遍历寻找可用节点,分发请求。与此同时,当前用户Session不能发生数据丢失,其余各节点服务器应保证用户Session数据同步。
为了搭建Tomcat集群,我将两个Tomcat分别部署到两台虚拟机上,确保网段一致。(这一步很关键,我最初将Tomcat1(192.168.49.132)
部署在虚拟机上,将Tomcat2(192.168.49.128)
部署在本机上,结果,网络总有问题,耽误了很多时间。
)
由于变换了IP,我需要修改Apache的/etc/apache2/mods-available/proxy.conf
文件:
- sudo vi /etc/apache2/mods-available/proxy.conf
sudo vi /etc/apache2/mods-available/proxy.conf
修改负载均衡节点如下:
- <Proxy balancer://zlex>
- BalancerMember ajp://192.168 . 49.128 : 8009 /zlex route=tomcat1
- BalancerMember ajp://192.168 . 49.132 : 8009 /zlex route=tomcat2
- </Proxy>
<Proxy balancer://zlex> BalancerMember ajp://192.168.49.128:8009/zlex route=tomcat1 BalancerMember ajp://192.168.49.132:8009/zlex route=tomcat2 </Proxy>
对于windows系统,不需要考虑网络问题,广播地址(这里用到224.0.0.0
和240.0.0.0
)默认开放,对于linux则需要通过命令开放地址。
Ubuntu上开放广播地址(eth0网卡):
- sudo route add -net 224.0 . 0.0 netmask 240.0 . 0.0 dev eth0
sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
然后通过-v
参数查看当前开放的广播地址:
- route -v
route -v
注意,重启后,该路由设置将丢失!
在Ubuntu下,可以考虑修改/etc/networks
文件!
如果有必要,Windows上开放广播地址(192.168.49.128本机地址):
- route add 224.0 . 0.0 mask 240.0 . 0.0 192.168 . 49.128
route add 224.0.0.0 mask 240.0.0.0 192.168.49.128
然后通过print
参数查看当前开放的广播地址:
- route print
route print
然后,修改tomcat的server.xml文件:
- sudo vi /etc/tomcat6/server.xml
sudo vi /etc/tomcat6/server.xml
在<Engine />
节点中加入如下内容:
- < Cluster className = "org.apache.catalina.ha.tcp.SimpleTcpCluster"
- channelSendOptions = "8" >
- < Manager className = "org.apache.catalina.ha.session.DeltaManager"
- expireSessionsOnShutdown = "false"
- notifyListenersOnReplication = "true" />
- < Channel className = "org.apache.catalina.tribes.group.GroupChannel" >
- < Membership className = "org.apache.catalina.tribes.membership.McastService"
- address = "224.0.0.0"
- port = "45564"
- frequency = "500"
- dropTime = "3000" />
- < Receiver className = "org.apache.catalina.tribes.transport.nio.NioReceiver"
- address = "192.168.49.1"
- port = "4000"
- autoBind = "100"
- selectorTimeout = "5000"
- maxThreads = "6" />
- < Sender className = "org.apache.catalina.tribes.transport.ReplicationTransmitter" >
- < Transport className = "org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
- </ Sender >
- < Interceptor className = "org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
- < Interceptor className = "org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" />
- </ Channel >
- < Valve className = "org.apache.catalina.ha.tcp.ReplicationValve"
- filter = ".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;" />
- < Valve className = "org.apache.catalina.ha.session.JvmRouteBinderValve" />
- < ClusterListener className = "org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
- < ClusterListener className = "org.apache.catalina.ha.session.ClusterSessionListener" />
- </ Cluster >
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="224.0.0.0" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="192.168.49.1" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"发表评论
-
NAT负载均衡技术 (转)
2011-08-10 11:09 1839转自 http://www.bbfish.net/Ap ... -
SSL原理解密(转)
2011-07-26 06:47 1566RSA公钥加密在计算机产 ... -
SSL 开发简述(Delphi) (转)
2011-07-26 06:34 2219一、 简介 现在网上有关 ... -
SSL协议 and How SSL works (转)
2010-12-20 11:54 1361SSL协议的工作流程: ... -
关于反向代理,负载均衡介绍 (转)
2010-10-19 06:05 1082一.反向代理的概念 什么是反向代理呢?其 ... -
征服 Apache + SVN (转)
2010-08-27 10:09 1079原文转自 http://snowolf.iteye.com/b ... -
征服 Apache + SSL (转)
2010-08-27 10:07 719原文转自 http://snowolf.iteye.com/b ... -
Dealing with DNS Leaks(转)
2010-07-30 19:32 1686The Problem When an applicatio ...
相关推荐
NULL 博文链接:https://snowolf.iteye.com/blog/743611
3. **Tomcat 5以上**: Apache Tomcat是一个开源的Servlet容器,用于部署Java Web应用。 4. **Eclipse 3.0**: 集成开发环境,支持Java和JavaScript开发,便于构建和调试Ajax应用。 **四、学习资源** 本资源可能包含...
8. 《Tomcat 权威指南》:做 Java Web 的一般都必须学习这个,为 Apache 的开源项目。 9. 《Head First Servlets & Jsp》:Servlet 和 Jsp 是 JavaEE 程序员必须要掌握好的。 10. 《Head First HTML与 CSS.XHTML 》...
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
前端分析-2023071100789
基于kinect的3D人体建模C++完整代码.cpp
搞机工具箱10.1.0.7z
GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟
auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
复件 复件 建设工程可行性研究合同[示范文本].doc
13考试真题最近的t64.txt
好用我已经解决报错问题
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
auto_gptq-0.4.2-cp38-cp38-win_amd64.whl
自动立体库设计方案.pptx
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!