nginx的session共享、springboot專案、redis集群
一、準備作業

實作zookeeper集群、dubbo集群、實作dubbo負載均衡!!!
沒有搭建好的可以看上篇文章->文章地址
主要ip和埠宣告:
- zookeeper集群配置
zookeeper配置在linux虛擬機上(因為不想開太多個linux虛擬機,所以配置在 一臺linux虛擬機上了,差別只在于修改ip地址)
| 包名稱 | ip地址 | 埠號 |
|---|---|---|
| zookeeper-2181 | 172.16.248.201 | 2181 |
| zookeeper-2182 | 172.16.248.201 | 2182 |
| zookeeper-2183 | 172.16.248.201 | 2183 |
- dubbo集群配置
- 消費者集群
配置在我的windows系統上了
- 消費者集群
| 應用名 | ip地址 | 埠號 |
|---|---|---|
| dubbodemo-consumer_1 | localhost | 2011 |
| dubbodemo-consumer_1 | localhost | 2012 |
| dubbodemo-consumer_1 | localhost | 2013 |
| dubbodemo-consumer_1 | localhost | 2014 |
- 服務者集群
配置在我的windows系統上了
| 應用名 | ip地址 | 埠號 |
|---|---|---|
| dubbodemo_provider_1 | localhost | 8081 |
| dubbodemo_provider_1 | localhost | 8082 |
二、引出session共享問題
上篇文章已經實作了nginx實作對消費者埠的分配,以及dubbo對提供者的負載均衡
可以知道當我們訪問www.ebuy.com時,nginx服務器會自動分配請求的服務器,再以下四臺服務器中輪詢選擇!!!
- 那么我們創建一個存盤session的業務,來看看會出現什么問題!!!
改造消費者的專案
修改pom.xml檔案
- 首先因為要用到HttpServletRequest的類,所以先引入jar包

- 然后引入我們的javax.servlet-api
<!--為了session-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
- pom.xml檔案整體
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn</groupId>
<artifactId>dubbodemo_customer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>dubbodemo_customer Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
<spring.version>5.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- dubbo相關 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--為了session-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<!-- 指定埠 -->
<port>2014</port>
<!-- 請求路徑 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
<finalName>dubbodemo_provider</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
修改controller

- helloController原始碼:
package cn.ebuy.controller;
import cn.ebuy.service.HelloService;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/demo")
public class HelloController {
@Reference
private HelloService helloService;
int port=2014;
@RequestMapping("/hello")
@ResponseBody
public String getName(String name){
//遠程呼叫
String result = helloService.sayHello(name);
System.out.println(port+result);
return port+result;
}
@RequestMapping("/toSession")
@ResponseBody
public String toSession(HttpServletRequest request){
request.getSession().setAttribute("USERS","xiaoming");
System.out.println("存放USERS進"+port+"埠的session中");
return "port:"+port+"->session"+":Success";
}
@RequestMapping("/doSession")
@ResponseBody
public String doSession(HttpServletRequest request){
String USERS= (String) request.getSession().getAttribute("USERS");
System.out.println("從埠"+port+"的session中取得USERS"+USERS);
return "port:"+port+"----USERS:"+USERS;
}
}
啟動服務
首先其中我們的虛擬機的zookeeper集群,然后啟動提供者集群,之后啟動我們的消費者單個專案(注意是單個,僅2011這一個專案),然后開啟我們的nginx服務器,最后進入dubbo-admin查看注冊情況!!!
- 測驗一下

- 那么此時我們開始啟動消費者集群2012->2014
開始測驗


那真是奇怪了,為什么就連相同服務器的session都拿不到了!!!
(因為nginx會認為你產生的新的會話—這一點可以具體百度)
session不共享引發的問題
- 那么session不共享,會引發什么問題呢?
因為nginx內部的負載均衡策略,我們每次請求的服務器可能不同,導致session不共享,那么舉個例子,你登錄系統后,一重繪再次讓你登錄!
可以說是web應用的災難性的問題!!!
三、解決nginx的session共享問題
1、ip_hash方式
在nginx內部,便存在解決session共享的方法,那就是ip_hash演算法,
ip_hash演算法,簡單來說就是你(220.181.38.251)去請求服務時,ip_hash演算法會將你的ip取值為hash值,然后給你分配服務器A,當你再次請求服務時,分配給你的還是服務器A,甚至只要是(220.181.38.xxx)的都是服務器A!
測驗
那么如何使用這個ip_hash演算法呢?
很簡單!!!
只需要在

- 然后重啟nginx服務
再次請求

- 可以說ip_hash是真的簡單粗暴,相當于對于請求一次后的你來說,不再“負載均衡”!!!
2、通過redis集群實作session共享
溫馨提示(記得把ip_hash的配置注釋掉,然后重啟服務)
- 作業原理
redis集群實作
session共享的原理就是將你的session資料存放進redis集群中,再次請求時,從redis中取得資料,從而實作session共享,
因為涉及到redis集群,為了更快的搭建專案,首先進行改造提供者和消費者的專案為(springboot專案)!!!
改造提供者專案
注意一定要選擇jdk1.8,zookeeper對jdk的兼容性極差,高版本都是問題(一小時的教訓!!!)
創建專案

注意主啟動類不在cn.ebuy目錄下,注意掃描包
(@SpringBootApplication(scanBasePackages = ))
注意接下來不要選任何jar包,因為后面我們會一起匯入!!!

匯入jar包
注意java版本必須是1.8
pom.xml檔案
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.ebuy</groupId>
<artifactId>springboot_dubbo_provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_dubbo_provider</name>
<description>springboot_dubbo_provider</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--web需要的jar包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--dubbo需要的jar-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.6</version>
</dependency>
<!--zookeeper需要的jar-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.6</version>
<exclusions>
<!--排除掉zookeeper內置的這個jar-->
<exclusion>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
創建service

- 這個注解原本是alibaba包下的,換為apache包下的(過時問題)
配置主組態檔
application.yaml(原本是application.properties,修改為yaml檔案)
注意超時時間必須配置(有可能會因為超時時間連不上,報錯)

拿來之前的普通的spring專案對比下

啟動專案

改造消費者專案
創建專案
- 同上面的提供者專案一樣,不要選擇任何jar

匯入jar包
注意這個jar不同于上面的提供者!!!
pom.xml檔案:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.ebuy</groupId>
<artifactId>springboot_dubbo_consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_dubbo_consumer</name>
<description>springboot_dubbo_consumer</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.6</version>
<exclusions>
<exclusion>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<!-- 實作對 Spring Session 使用 Redis 作為資料源的自動化配置 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- 實作對 Spring Data Redis 的自動化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<!-- 去掉對 Lettuce 的依賴,因為 Spring Boot 優先使用 Lettuce 作為 Redis 客戶端 -->
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 Jedis 的依賴,這樣 Spring Boot 實作對 Jedis 的自動化配置 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
創建service

創建controller

原始碼:
package cn.ebuy.controller;
import cn.ebuy.service.HelloService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/demo")
public class HelloController {
@Reference
private HelloService helloService;
int port=2014;
@RequestMapping("/hello")
@ResponseBody
public String getName(String name){
//遠程呼叫
String result = helloService.sayHello(name);
System.out.println(port+result);
return port+result;
}
@RequestMapping("/toSession")
@ResponseBody
public String toSession(HttpServletRequest request){
request.getSession().setAttribute("USERS","xiaoming");
System.out.println("存放USERS進"+port+"埠的session中");
return "port:"+port+"->session"+":Success";
}
@RequestMapping("/doSession")
@ResponseBody
public String doSession(HttpServletRequest request){
String USERS= (String) request.getSession().getAttribute("USERS");
System.out.println("從埠"+port+"的session中取得USERS"+USERS);
return "port:"+port+"----USERS:"+USERS;
}
}
創建util包(關鍵)

搭建redis集群
這里不再詳細講解,可以看這個文章,或者百度均可!!!
我的redis集群的密碼都是123456,然后埠號是6379、6380、6381、6382、6383和6384,
- 搭建完成之后,進行啟動!!!
配置主組態檔

測驗啟動
因為要測驗多個消費者,所以要一個專案跑多個埠服務,那么如何做到呢?(小技巧)

然后分別運行一次修改一次application.yaml中的server:port(2011->2014
對應你的nginx中配置的內容!!!)和controller中的port變數(這個只是為了便于區分,看出效果!!),
- 分別啟動后看到

- 最后測驗我們的session共享嗎

- 然后我們打開redis可視化工具看下內容

這樣就算是完成了!!!
感謝觀看!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/294907.html
標籤:其他

