• 【技术分享】使用nginx完成动静分离➕集成SpringSession➕集成sentinel➕集成seata


    🥳🥳Welcome 的Huihui's Code World ! !🥳🥳

    接下来看看由辉辉所写的关于技术点的相关分享吧

    目录

    🥳🥳Welcome 的Huihui's Code World ! !🥳🥳

    一、 使用nginx完成动静分离

    1.下载nginx

    2.进入conf目录,并修改nginx.conf配置文件

    3.动静分离

    4.将静态文件放置再nginx中

    5.运行nginx根目录下的nginx.exe启动nginx

    6.修改项目中静态资源的路径

    二、 集成SpringSession

    1.引入依赖

    2.在需要使用到springsession的模块做以下配置

    3.编写代码完成登录功能

    4.前端显示

    三、 集成sentinel

    1.导入pom依赖

    2.在application文件中进行配置

    3.浏览器访问sentinel

    四、集成seata

    1.下载seata

    2.修改配置文件及初始化

    ①seata-server-1.4.0.zip​​​​​​​

    ②修改file.conf

    ③创建数据库Seata并初始化数据表

    3.启动seata服务

    4.使用Seata实现事务控制

    1.初始化数据表

    2.添加配置

    ①DataSourceProxyConfig

    ②application.yml

    ③registry.conf

    ③bootstrap.yaml


    一、 使用nginx完成动静分离

    1.下载nginx

    2.进入conf目录,并修改nginx.conf配置文件

    其中也可以完成反向代理的功能

    1. #user nobody;
    2. worker_processes 1;
    3. #error_log logs/error.log;
    4. #error_log logs/error.log notice;
    5. #error_log logs/error.log info;
    6. #pid logs/nginx.pid;
    7. events {
    8. worker_connections 1024;
    9. }
    10. http {
    11. include mime.types;
    12. default_type application/octet-stream;
    13. #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    14. # '$status $body_bytes_sent "$http_referer" '
    15. # '"$http_user_agent" "$http_x_forwarded_for"';
    16. #access_log logs/access.log main;
    17. sendfile on;
    18. #tcp_nopush on;
    19. #keepalive_timeout 0;
    20. keepalive_timeout 65;
    21. #gzip on;
    22. server
    23. {
    24. listen 80;
    25. server_name product.zmall.com;
    26. proxy_redirect off;
    27. proxy_set_header Host $host;
    28. proxy_set_header X-Real-IP $remote_addr;
    29. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    30. location / {
    31. proxy_pass http://127.0.0.1:8000/product-serv/;
    32. }
    33. }
    34. server
    35. {
    36. listen 80;
    37. server_name user.zmall.com;
    38. proxy_redirect off;
    39. proxy_set_header Host $host;
    40. proxy_set_header X-Real-IP $remote_addr;
    41. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    42. client_max_body_size 0;
    43. chunked_transfer_encoding on;
    44. location / {
    45. proxy_pass http://127.0.0.1:8000/user-serv/;
    46. }
    47. }
    48. }

    3.动静分离

    1. server
    2. {
    3. listen 80;
    4. server_name images.zmall.com;
    5. location / {
    6. root html;
    7. index index.html;
    8. }
    9. }

    4.将静态文件放置再nginx中

    5.运行nginx根目录下的nginx.exe启动nginx

    6.修改项目中静态资源的路径

    我使用了一个公共的文件,再里面使用了一个base标签,这样其他页面引用这个文件就可以用到其中的静态资源了。

    1. <#assign ctx>
    2. ${springMacroRequestContext.contextPath}/
    3. <base href="http:images.zmall.com/"/>

    这里的域名也需要做一个域名映射

    C:\Windows\System32\drivers\etc\hosts

    二、 集成SpringSession

    使用其来完成登录成功之后,在首页显示当前用户信息【跨服务】

    1.引入依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-redisartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>org.springframework.sessiongroupId>
    7. <artifactId>spring-session-data-redisartifactId>
    8. dependency>
    9. <dependency>
    10. <groupId>org.apache.commonsgroupId>
    11. <artifactId>commons-pool2artifactId>
    12. dependency>

    2.在需要使用到springsession的模块做以下配置

    1. spring:
    2. session:
    3. redis:
    4. flush-mode: on_save
    5. namespace: session.zmall
    6. cleanup-cron: 0 * * * * *
    7. store-type: redis
    8. timeout: 1800
    9. redis:
    10. host: localhost
    11. port: 6379
    12. password: 123456
    13. jedis:
    14. pool:
    15. max-active: 100
    16. max-wait: 10
    17. max-idle: 10
    18. min-idle: 10
    19. database: 0

    3.编写代码完成登录功能

    1. package com.wh.user.service.impl;
    2. import com.alibaba.nacos.common.utils.MD5Utils;
    3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    4. import com.wh.user.pojo.User;
    5. import com.wh.user.mapper.UserMapper;
    6. import com.wh.user.service.IUserService;
    7. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    8. import com.wh.user.utils.JsonResponseBody;
    9. import com.wh.user.utils.JsonResponseStatus;
    10. import com.wh.user.vo.UserVo;
    11. import dto.UserDto;
    12. import org.springframework.beans.BeanUtils;
    13. import org.springframework.stereotype.Service;
    14. import org.springframework.util.DigestUtils;
    15. import javax.servlet.http.HttpServletRequest;
    16. import javax.servlet.http.HttpServletResponse;
    17. import javax.servlet.http.HttpSession;
    18. import java.nio.charset.StandardCharsets;
    19. import java.security.MessageDigest;
    20. import java.security.NoSuchAlgorithmException;
    21. import java.util.UUID;
    22. /**
    23. *

    24. * 服务实现类
    25. *

    26. *
    27. * @author baomidou
    28. * @since 2024-02-21
    29. */
    30. @Service
    31. public class UserServiceImpl extends ServiceImpl implements IUserService {
    32. /**
    33. * 登录
    34. * @param userVo
    35. * @return
    36. */
    37. @Override
    38. public JsonResponseBody userLogin(UserVo userVo) {
    39. //通过传递过来的用户名去数据库中查询对应的对象
    40. User user = this.getOne(new QueryWrapper().eq("loginName", userVo.getLoginName()));
    41. //做密码判断【数据库的密码是经过加密的】
    42. //将用户传递过来的密码加密
    43. String userpwd = DigestUtils.md5DigestAsHex(userVo.getPassword().getBytes());
    44. //加密之后与数据库中的用户密码进行对比
    45. if(!userpwd.equals(user.getPassword())){
    46. //如果密码不匹配,则提示相关错误信息
    47. return JsonResponseBody.other(JsonResponseStatus.LOGIN_NO_EQUALS);
    48. }
    49. //如果登录成功,就进行属性复制
    50. UserDto userDto = new UserDto();
    51. //属性复制
    52. BeanUtils.copyProperties(user,userDto);
    53. return JsonResponseBody.success();
    54. }
    55. }
    1. package com.wh.user.controller;
    2. import com.wh.user.service.IUserService;
    3. import com.wh.user.utils.JsonResponseBody;
    4. import com.wh.user.vo.UserVo;
    5. import dto.UserDto;
    6. import org.springframework.beans.BeanUtils;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.web.bind.annotation.RequestMapping;
    9. import org.springframework.web.bind.annotation.ResponseBody;
    10. import org.springframework.web.bind.annotation.RestController;
    11. import javax.servlet.http.HttpServletRequest;
    12. import javax.servlet.http.HttpServletResponse;
    13. /**
    14. *

    15. * 前端控制器
    16. *

    17. *
    18. * @author baomidou
    19. * @since 2024-02-21
    20. */
    21. @RestController
    22. public class UserController {
    23. @Autowired
    24. private IUserService userService;
    25. @Autowired
    26. private HttpServletRequest request;
    27. /**
    28. * 用户登陆功能实现
    29. * @return
    30. */
    31. @RequestMapping("/userLogin")
    32. public JsonResponseBody userLogin(UserVo userVo){
    33. //设置当前用户的登录信息
    34. request.getSession().setAttribute("user",userVo);
    35. //调用登录的方法
    36. JsonResponseBody user = userService.userLogin(userVo);
    37. return user;
    38. }
    39. }

    在跳首页的controller方法中获取当前登录用户的session信息

    1. @Autowired
    2. private IProductService productService;
    3. @Autowired
    4. private HttpServletRequest request;
    5. /**
    6. * 首页跳转
    7. * @param model
    8. * @return
    9. */
    10. @RequestMapping("/index.html")
    11. public String index(Model model){
    12. //获取当前用户的登录信息
    13. UserDto user = (UserDto)request.getSession().getAttribute("user");
    14. //按照商品的销量降序排序获取销量排名Top5的商品
    15. List products = productService.list(new QueryWrapper()
    16. .orderByDesc("hot")
    17. .last("limit 4"));
    18. model.addAttribute("top4",products);
    19. model.addAttribute("user",user);
    20. return "Index";
    21. }

    4.前端显示

    1. "soubg">
    2. "sou">
    3. "fr">
    4. "fl">你好,
    5. <#if user??>
    6. ${user.loginName}
    7. if>
    8. "fl">| 关注我们:

三、 集成sentinel

1.导入pom依赖

到网关中

  1. <dependency>
  2. <groupId>com.alibaba.cloudgroupId>
  3. <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
  4. dependency>

2.在application文件中进行配置

  1. sentinel:
  2. transport:
  3. port: 9998 #跟控制台交流的端口,随意指定一个未使用的端口即可
  4. dashboard: localhost:9999 # 指定控制台服务的地址
  5. eager: true #当服务启动时是否与sentinel建立连接
  6. web-context-unify: false # 关闭URL PATH聚合

3.浏览器访问sentinel

在此之前需要启动sentinel的那个jar包

  1. # 直接使用jar命令启动项目(控制台本身是一个SpringBoot项目)
  2. java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.4.jar

四、集成seata

1.下载seata

下载地址icon-default.png?t=N7T8http://Release v1.3.0 · apache/incubator-seata · GitHubRelease v1.3.0 · apache/incubator-seata · GitHub

2.修改配置文件及初始化

①seata-server-1.4.0.zip

将下载得到的seata-server-1.4.0.zip(非源码包)压缩包进行解压

  • 配置seata-1.4.0.zip(源码包)

修改seata-1.4.0中script/config-center目录中的config.txt配置:

  1. store.mode=db   #修改存储方式为db
  2. ...
  3. store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true   #修改数据库名
  4. store.db.user=root     #修改数据库账号
  5. store.db.password=1234 #修改数据库密码
  • 初始化Seata配置到Nacos中

在seata-1.4.0\script\config-center\nacos目录中右键选择git bash here,运行git命令窗口。并输入以下命令:

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -u nacos -w nacos
参数说明
-hnacos注册中心IP地址,默认是localhost
-pnacos注册中心端口,默认是8848
-gnacos配置中心分组,默认是SEATA_GROUP
-tnacos配置中心namespace命名空间名称,默认是'',即public默认命名空间
-unacos注册中心账号
-wnacos注册中心密码

执行成功后可以打开Nacos的控制台,在配置列表中,可以看到初始化了很多Group为SEATA_GROUP 的配置。

②修改file.conf

将mode=“type”修改成mode="db" 2.设置数据库名、用户账号及密码

③创建数据库Seata并初始化数据表

解压seata-1.4.0源码包,并进入到seata-1.4.0\script\server\db目录,复制运行mysql.sql脚本完成seata服务端数据库初始化工作。【记得先创建一个数据库:seata】

④修改registry.conf

  1. registry {
  2.   type = "nacos"                     #这里使用nacos为注册中心,将type修改成nacos
  3.   nacos {
  4.       application = "seata-server"   #注册的服务名
  5.       serverAddr = "127.0.0.1:8848" #nacos注册中心地址及端口
  6.       group = "SEATA_GROUP" #服务注册分组
  7.       namespace = ""       #namespace是服务注册时的命名空间,可不填,不填默认public
  8.       cluster = "default"   #默认即可
  9.       username = "nacos"   #nacos的登录账号
  10.       password = "nacos"   #nacos的登录密码
  11.   }
  12. }
  13. config {
  14.   type = "nacos"
  15.   nacos {
  16.       serverAddr = "127.0.0.1:8848"
  17.       namespace = ""
  18.       group = "SEATA_GROUP"
  19.       username = "nacos"
  20.       password = "nacos"
  21.   }
  22. }

registry:指定注册中心,将seata-server注册到指定位置 config: 指定配置中心

3.启动seata服务

直接进入seata服务的seata\bin目录下,双击运行seata-server.bat文件即可。或者使用以下命令方式运行:

cd bin
seata-server.bat -p 9000 -m file
seata-server.bat -h ip地址 -p 9000 -m file

-p 9000:指定监听端口,默认为8091

-m file: 模式

启动后在 Nacos 的服务列表下面可以看到一个seata的服务。

4.使用Seata实现事务控制

1.初始化数据表

进入源码包seata-1.4.0\script\client\at\db目录,复制并运行数据库脚本完成undo_log表创建,这是Seata记录事务日志要用到的表。

  1. CREATE TABLE `undo_log`
  2. (
  3. `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  4. `branch_id` BIGINT(20) NOT NULL,
  5. `xid` VARCHAR(100) NOT NULL,
  6. `context` VARCHAR(128) NOT NULL,
  7. `rollback_info` LONGBLOB NOT NULL,
  8. `log_status` INT(11) NOT NULL,
  9. `log_created` DATETIME NOT NULL,
  10. `log_modified` DATETIME NOT NULL,
  11. `ext` VARCHAR(100) DEFAULT NULL,
  12. PRIMARY KEY (`id`),
  13. UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
  14. ) ENGINE = INNODB
  15. AUTO_INCREMENT = 1
  16. DEFAULT CHARSET = utf8;

2.添加配置

①DataSourceProxyConfig
  1. package com.zking.zmall.config;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import io.seata.rm.datasource.DataSourceProxy;
  4. import io.seata.rm.datasource.xa.DataSourceProxyXA;
  5. import org.springframework.boot.context.properties.ConfigurationProperties;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.context.annotation.Primary;
  9. import javax.sql.DataSource;
  10. @Configuration
  11. public class DataSourceProxyConfig {
  12. @Bean
  13. @ConfigurationProperties(prefix = "spring.datasource")
  14. public DruidDataSource druidDataSource() {
  15. return new DruidDataSource();
  16. }
  17. @Primary
  18. @Bean("dataSourceProxy")
  19. public DataSource dataSource(DruidDataSource druidDataSource) {
  20. //AT模式
  21. return new DataSourceProxy(druidDataSource);
  22. //XA模式
  23. //return new DataSourceProxyXA(druidDataSource);
  24. }
  25. }

在启动类(使用到SeaTa)上排除DataSource数据源自动配置类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
②application.yml

在需要进行分布式事务的各个微服务中的application.yml数据源更新成阿里巴巴的DruidDataSource

  1. #type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikari
  2. type: com.alibaba.druid.pool.DruidDataSource
③registry.conf

在微服务模块中的resources目录下添加seata的配置文件 registry.conf,该配置文件来自于seata-server/conf目录下的配置文件。

  1. registry {
  2. type = "nacos"
  3. nacos {
  4. serverAddr = "localhost"
  5. namespace = "public"
  6. cluster = "default"
  7. }
  8. }
  9. config {
  10. type = "nacos"
  11. nacos {
  12. serverAddr = "localhost"
  13. namespace = "public"
  14. cluster = "default"
  15. }
  16. }
③bootstrap.yaml

请注意spring.cloud.alibaba.seata.tx-service-group=my_test_txgroup配置。这里的my_test_tx_group名称必须与seata源码包中的config.txt配置文件中的名字一致。重要,重要,重要!!!

请打开seata源码包目录seata-1.4.0\script\config-center\下的config.txt去进行配置。

  1. spring:
  2. application:
  3. name: service-product
  4. cloud:
  5. nacos:
  6. config:
  7. server-addr: localhost:8848 # nacos的服务端地址
  8. namespace: public
  9. group: SEATA_GROUP
  10. alibaba:
  11. seata:
  12. tx-service-group: my_test_tx_group

注意:一定要加一个配置

  1. <dependency>
  2. <groupId>org.springframework.cloudgroupId>
  3. <artifactId>spring-cloud-starter-bootstrapartifactId>
  4. dependency>

好啦,今天的分享就到这了,希望能够帮到你呢!😊😊 

  • 相关阅读:
    【C#设计模式】单例模式
    Android 内存泄漏分析思路和案例剖析
    什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的 IE?
    java计算机毕业设计网上宠物售卖平台源代码+数据库+系统+lw文档
    从零到上亿用户,我是如何一步步优化MySQL数据库的?(建议收藏)
    CCF ChinaSoft 2023 论坛巡礼|软件测试产教研融合论坛
    vue如何使用深度选择器?
    【Spring Boot 源码学习】OnClassCondition 详解
    OpenCascade模型解析-详细分解模型结构
    【目标】新学期计划与目标
  • 原文地址:https://blog.csdn.net/m0_74315688/article/details/136262223