$oraUser="nihao";//數(shù)據(jù)庫賬號
創(chuàng)新互聯(lián)建站是專業(yè)的解放網(wǎng)站建設(shè)公司,解放接單;提供成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行解放網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
$oraPass="123456"; //密碼
$oraDB="(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SID=orcl)))"; //SID要和連接的數(shù)據(jù)庫對應(yīng)上
$conn = ociLOGOn($oraUser,$oraPass,$oraDB) ;//連接
$rs_search=OCIParse($conn, $sql_search); //執(zhí)行SQL語句
OCIExecute($rs_search);
//$rs_search這個是結(jié)果集可以用
$row=oci_fetch_array($rs_search);//把數(shù)據(jù)拿出來 這是一條數(shù)據(jù)寫法 多條循環(huán)
有不明白的HI我
在這個互聯(lián)網(wǎng)高度發(fā)達的時代,許多應(yīng)用的用戶動輒成百上千萬,甚至上億。為了支持海量用戶的訪問,應(yīng)用服務(wù)器集群這種水平擴展的方式是最常用的。這種情形下,就會涉及到許多單機環(huán)境下完全不需要考慮的問題,這其中session的創(chuàng)建、共享和存儲是最常見之一。
在單機環(huán)境中,Session的創(chuàng)建和存儲都是由同一個應(yīng)用服務(wù)器實例來完成,而存儲也僅是內(nèi)存中,最多會在正常的停止服務(wù)器的時候,把當前活動的Session鈍化到本地,再次啟動時重新加載。
而多個實例之間,Session數(shù)據(jù)是完全隔離的。而為了實現(xiàn)Session的高可用,多實例間數(shù)據(jù)共享是必然的,下面我們以Redis 的SessionManager實現(xiàn)多Tomcat實例Session共享的配置為例,我們來梳理下一般session共享的流程:
添加具體要使用的manager的Jar文件及其依賴
redis session manager依賴jedis, commons-pool, commons-pool2
對應(yīng)版本的redis session manager的jar文件
在TOMCAT_HOME/conf/context.xml中增加如下配置
Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" /
Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379" database="0"
maxInactiveInterval="30" /
其中host和port等替換為對應(yīng)的配置信息
啟動多個Tomcat實例,以自帶的examples應(yīng)用為例進行驗證
訪問examples應(yīng)用的servlets/servlet/SessionExample,
在頁面中添加數(shù)據(jù)到session中,并查看頁面上對應(yīng)的session信息
訪問另一個實例上相同應(yīng)用的頁面,查看session信息,兩者應(yīng)該是一致的
使用redis-cli查看redis中存儲的對應(yīng)數(shù)據(jù),相應(yīng)的sessionId對應(yīng)的數(shù)據(jù)已經(jīng)保存了下來
以上是一個基本的配置過程,而在這些配置與驗證的步驟中,第二步是核心邏輯實現(xiàn)。 前面的文章,曾介紹過Tomcat的Valve,在請求處理時,Pipeline中的各個Valve的invoke方法會依次執(zhí)行。Tomcat的AccessLogValve介紹
此處的session處理,就是以一個自定義Valve的形式進行的。關(guān)于Session的文章,前面也寫過幾篇,會附在結(jié)尾處。
以下是RedisSessionhandlerValve的invoke方法,我們看,主要是在Valve執(zhí)行后進行Session的存儲或移除。
public void invoke(Request request, Response response) {
try {
getNext().invoke(request, response);
} finally {
final Session session = request.getSessionInternal(false);
storeOrRemoveSession(session);
manager.afterRequest();
}
}
而session的保存和移除又是通過manager執(zhí)行的。 manager.save(session); manager.remove(session);
這里,manager就是前面定義的RedisSessionManager。默認單實例情況下,我們使用的都是StandardManager,對比一下兩者,標準的Manager對于session的創(chuàng)建和刪除,都會調(diào)到其父類ManagerBase中相應(yīng)的方法,
public void add(Session session) {
sessions.put(session.getIdInternal(), session);
int size = getActiveSessions();
if( size maxActive ) {
synchronized(maxActiveUpdateLock) {
if( size maxActive ) {
maxActive = size;
}
}
}
}
public void remove(Session session, boolean update) {
if (session.getIdInternal() != null) {
sessions.remove(session.getIdInternal());
}
}
我們來看,由于其只保存在內(nèi)存的Map中protected MapString, Session sessions = new
ConcurrentHashMap(),每個Tomcat實例都對于不同的map,多個實例間無法共享數(shù)據(jù)。
對應(yīng)到RedisSessionManager對于session的處理,都是直接操作redis,基本代碼是下面這個樣:
public void save(Session session) throws IOException {
Jedis jedis = null;
Boolean error = true;
try {
RedisSession redisSession = (RedisSession) session;
Boolean sessionIsDirty = redisSession.isDirty();
redisSession.resetDirtyTracking();
byte[] binaryId = redisSession.getId().getBytes();
jedis = acquireConnection();
if (sessionIsDirty || currentSessionIsPersisted.get() != true) {
jedis.set(binaryId, serializer.serializeFrom(redisSession));
}
currentSessionIsPersisted.set(true);
jedis.expire(binaryId, getMaxInactiveInterval());
} }
移除時的操作是這樣的
public void remove(Session session, boolean update) {
Jedis jedis = null;
Boolean error = true;
log.trace("Removing session ID : " + session.getId());
try {
jedis = acquireConnection();
jedis.del(session.getId());
error = false;
} finally {
if (jedis != null) {
returnConnection(jedis, error);
}
}
}
而此時,多個Tomcat實例都讀取相同的Redis,session數(shù)據(jù)是共享的,其它實例的初始請求過來時,由于會執(zhí)行findSession的操作,此時會從Redis中加載session,
public Session findSession(String id) throws IOException {
RedisSession session;
if (id == null) {
session = null;
currentSessionIsPersisted.set(false);
} else if (id.equals(currentSessionId.get())) {
session = currentSession.get();
} else {
session = loadSessionFromRedis(id); // 看這里,會從redis中l(wèi)oad
if (session != null) {
currentSessionIsPersisted.set(true);
}
}
currentSession.set(session);
currentSessionId.set(id);
return session;
}
從而可以保證在一個實例被切換后,另外的實例可以繼續(xù)響應(yīng)同一個session的請求。
以上即為Redis實現(xiàn)session共享高可用的一些關(guān)鍵內(nèi)容。有興趣的朋友可以看下通過Memcached實現(xiàn)高可用,也是這個原理。順著這個思路,如果你有將Session存儲在其它地方的需求時,完全可以寫一個出來,自己動手,豐衣足食。
總結(jié)一下,我們是通過自定義的Valve來實現(xiàn)請求后session的攔截,同時,使用自定義的SessionManager,來滿足不同的session創(chuàng)建與存儲的需求。而至于是存儲在Redis/Memcached中,還是存儲在DB中,只是位置的區(qū)別。原理,是一致的。
個人建議 至少4臺服務(wù)器,并且最好是以局域網(wǎng)方式互通(服務(wù)器4可以完全獨立)
服務(wù)器1和服務(wù)器2都只放php代碼程序,暴露在外網(wǎng),分別當電信服務(wù)器和網(wǎng)通服務(wù)器
服務(wù)器3只放數(shù)據(jù)庫,通過用戶權(quán)限,僅允許被服務(wù)器1和2訪問——不暴露在外網(wǎng)
服務(wù)器4只放附件,暴露在外網(wǎng),所有的附件請求,都直接對這個服務(wù)器進行
需要指出的是,你如果作為網(wǎng)站管理者,每次管理數(shù)據(jù)庫,都要用1或者2當跳板,才可以訪問。
當前題目:php數(shù)據(jù)庫集群 mysql數(shù)據(jù)庫集群
鏈接地址:http://www.rwnh.cn/article26/dodoscg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、移動網(wǎng)站建設(shè)、面包屑導(dǎo)航、、網(wǎng)站設(shè)計、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)