注册微服务用Nacos+Sential+Dubbo改造
一:安装nacos
访问地址: http://localhost:8848/nacos/#/serviceManagement?dataId=&group=&appName=&namespace=&serverId=.
配置中心
二:sentinel
启动命令:java -jar sentinel-dashboard-1.7.0.jar &
访问地址:
http://localhost:8080/#/dashboard.
去掉热部署引用
父pom.xml引入
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-dubboartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-apache-dubbo-adapterartifactId>
dependency>
<dependency>
<groupId>com.qchgroupId>
<artifactId>lagou-service-dubbo-apiartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
yml改造
server:
port: 8084
spring:
application:
name: lagou-service-email
mail:
#smtp服务主机 qq邮箱则为smtp.qq.com
host: smtp.qq.com
#服务协议
protocol: smtp
# 编码集
default-encoding: UTF-8
#发送邮件的账户
username: 222
#授权码
password: 22
test-connection: true
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
################ 配置nacos server地址
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
namespace: 21ccc
group: DEFAULT_GROUP
file-extension: yaml
# springboot中暴露健康检查等断点接⼝
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接⼝的细节
endpoint:
health:
show-details: always
dubbo:
scan:
# dubbo 服务扫描基准包
base-packages: com.qch.edu.service.impl
protocol:
# dubbo 协议
name: dubbo
# dubbo 协议端⼝( -1 表示⾃增端⼝,从 20880 开始)
port: -1
registry:
# 挂载到 Spring Cloud 的注册中⼼
address: spring-cloud://localhost
3.改造impl类
@Service使用Dubbo,被使用时使用@reference
package com.qch.edu.service.impl;
import com.qch.edu.service.EmailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import javax.annotation.Resource;
/**
* @Author qch
* @Date 2021/2/28
*/
@Service
@Slf4j
public class EmailServiceImpl implements EmailService {
@Value("${spring.mail.username}")
private String provider;
@Resource
private JavaMailSender sender;
/*发送邮件的方法*/
public void sendEmail(String acceptor, String title, String content){
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(provider); //发送者
message.setTo(acceptor); //接受者
message.setSubject(title); //发送标题
message.setText(content); //发送内容
sender.send(message);
System.out.println("邮件发送成功");
}
}
1.pom.xml
<dependencies>
<dependency>
<groupId>com.qchgroupId>
<artifactId>lagou-service-commonartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-dubboartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-apache-dubbo-adapterartifactId>
dependency>
<dependency>
<groupId>com.qchgroupId>
<artifactId>lagou-service-dubbo-apiartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
这里引入哨兵sentinel,同样需要在yaml文件中添加配置
2.yaml
既要注册又要订阅
server:
port: 8085
spring:
application:
name: lagou-service-code
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://10.222/springbootdata? serverTimezone=UTC
name: 22
password: 22
jpa:
database: MySQL
show-sql: true
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰命名转换为下划线命名
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
################ 配置nacos server地址
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 127.0.0.1:8080 # sentinel dashboard/console地址
port: 8719 # sentinel会在该端⼝启动http server,那么这样 的话,控制台定义的⼀些限流等规则才能发送传递过来,#如果8719端⼝被占⽤,那么会依次+1
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接⼝的细节
endpoint:
health:
show-details: always
dubbo:
registry:
# 挂载到 Spring Cloud 注册中⼼
address: spring-cloud://localhost
cloud:
# 订阅服务提供⽅的应⽤列表,订阅多个服务提供者使⽤ "," 连接
subscribed-services: lagou-service-email
scan:
base-packages: com.qch.edu.service.impl
protocol:
port: -1
name: dubbo
3.改造业务代码
package com.qch.edu.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.qch.edu.config.SentinelHandlersClass;
import com.qch.edu.pojo.AuthCodeDO;
import com.qch.edu.service.AuthCodeService;
import com.qch.edu.service.EmailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @Author qch
* @Date 2021/3/1
*/
@RestController
@Slf4j
@RequestMapping("/code")
public class CodeController {
@Reference
private EmailService emailService;
@Autowired
private AuthCodeService authCodeService;
@GetMapping("/create/{email}")
@SentinelResource(value = "createCode",blockHandlerClass = SentinelHandlersClass.class,blockHandler ="handleException") //类似于hystrix中的@HystrixCommand注解
public boolean createCode(@PathVariable String email) {
//Math.random()*(n-m)+m;//产生一个[0,1)之间的随机数
int number = (int)(Math.random()*(1000000-100000)+100000);
AuthCodeDO code = new AuthCodeDO();
AuthCodeDO byEmail = authCodeService.findByEmail(email);
if(byEmail!=null)
{
code.setId(byEmail.getId());
//一分钟内只能获取一次
Date limitTime= new Date(byEmail.getCreateTime().getTime() + 60000);
if(limitTime.after(new Date()))
{
log.error("一分钟内只能获取一次验证码");
System.out.println("一分钟内只能获取一次验证码");
return false;
}
}
code.setCode(String.valueOf(number));
code.setEmail(email);
Date create=new Date();
//十分钟后超时
Date expire= new Date(create.getTime() + 600000);
code.setCreateTime(create);
code.setExpireTime(expire);
try {
authCodeService.createCode(code);
}catch (Exception e){
log.error("保存code失败");
return false;
}
//调用email服务
emailService.sendEmail(email,"验证码",String.valueOf(number));
return true;
}
@GetMapping("/validate/{email}/{code}")
public int validate(@PathVariable String email,@PathVariable String code) {
AuthCodeDO byEmail = authCodeService.findByEmail(email);
if(byEmail==null){
return -1;//不存在
}
if (byEmail.getCode().equals(code))
{
if(byEmail.getExpireTime().before(new Date())){
return 2;//超时
}
return 0;//正确
}else {
return 1;//错误
}
}
}
熔断降级代码
public class SentinelHandlersClass {
public static boolean createCode( String email, BlockException blockException){
return true;
};
}
Description:
Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.
原因是spring-boot-starter-webflux 和spring-boot-starter-web 冲突因此需要exclusion
<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.0modelVersion>
<groupId>com.qchgroupId>
<artifactId>lagou-cloud-gateway-server-9003-nsdartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-commonsartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.4version>
<scope>providedscope>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-coreartifactId>
<version>2.2.11version>
dependency>
<dependency>
<groupId>javax.xml.bindgroupId>
<artifactId>jaxb-apiartifactId>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-implartifactId>
<version>2.2.11version>
dependency>
<dependency>
<groupId>org.glassfish.jaxbgroupId>
<artifactId>jaxb-runtimeartifactId>
<version>2.2.10-b140310.1920version>
dependency>
<dependency>
<groupId>javax.activationgroupId>
<artifactId>activationartifactId>
<version>1.1.1version>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-dubboartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-apache-dubbo-adapterartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>com.qchgroupId>
<artifactId>lagou-service-dubbo-apiartifactId>
<version>1.0-SNAPSHOTversion>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Greenwich.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
exclusion>
exclusions>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>8source>
<target>8target>
<encoding>utf-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
2.yaml改造
server:
port: 9003
spring:
application:
name: lagou-cloud-gateway
cloud:
nacos:
discovery:
################ 配置nacos server地址
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
namespace: 2ssad
group: DEFAULT_GROUP
file-extension: yaml
gateway:
routes: # 路由可以有多个
- id: service-user-router # 我们自定义的路由 ID,保持唯一
uri: http://127.0.0.1:8083 # 目标服务地址 自动投递微服务(部署多实例) 动态路由:uri配置的应该是一个服务名称,而不应该是一个具体的服务实例的地址
#uri: lb://lagou-service-user # gateway网关从服务注册中心获取实例信息然后负载后路由
predicates: # 断言:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默 认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
- Path=/api/user/**
filters:
- StripPrefix=1
- id: service-code-router # 我们自定义的路由 ID,保持唯一
uri: http://127.0.0.1:8085 # 目标服务地址
#http://localhost:9002/resume/openstate/1545132
#http://127.0.0.1:8081/openstate/1545132
#uri: lb://lagou-service-code
predicates: # 断言:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默 认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
- Path=/api/code/**
filters:
- StripPrefix=1
- id: service-email-router # 我们自定义的路由 ID,保持唯一
uri: http://127.0.0.1:8084 # 目标服务地址
#http://localhost:9002/resume/openstate/1545132
#http://127.0.0.1:8081/openstate/1545132
#uri: lb://lagou-service-email
predicates: # 断言:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默 认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
- Path=/api/email/**
filters:
- StripPrefix=1
main:
allow-bean-definition-overriding: true
#filters:
#- StripPrefix=1
dubbo:
registry:
# 挂载到 Spring Cloud 注册中⼼
address: spring-cloud://localhost
cloud:
# 订阅服务提供⽅的应⽤列表,订阅多个服务提供者使⽤ "," 连接
subscribed-services: lagou-service-user