SpringCloud开发
版本控制
<!-- SpringBoot版本管理 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<!--定义springcloud使用版本号-->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<!--全局管理springcloud版本,并不会引入具体依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
服务注册与发现
Eureka
Eureka-Server
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka服务端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
application.properties
# 执行服务端口
server.port=8761
# 指定服务名称 唯一标识
spring.application.name=eurekaServer
# 指定服务注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:8761
# 关闭erueka client立即注册
eureka.client.fetch-registry=false
# 让当前应用仅仅是服务注册中心
eureka.client.register-with-eureka= false
# 关闭自我保护机制
eureka.server.enable-self-preser=false
# 设置刷新时间
eureka.server.eviction-interval-timer-in-ms=3000
开启
EurekaServer服务
@SpringBootApplication
@EnableEurekaServer // 开启Eureka服务端
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
EureKa-Client
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.properties
# 服务端口号
server.port= 8762
# 服务名称
spring.application.name= EurekaClient
# 指定服务注册中心的地址
eureka.client.service-url.defaultZone= http://localhost:8761/eureka
# 用来修改eureka server默认接受心跳的最大时间默认是90s .
eureka.instance.lease-expiration-duration-in-seconds=10
# 指定客户端多久向eureka server发送 - -次心跳默认是30s
eureka.instance.lease-renewal-interval-in-seconds=5
开启
EurekaClient服务
@SpringBootApplication
@EnableEurekaClient // 开启Eureka客户端
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
Consul(重点)
Consul 的使用
<!-- 切换目录 -->
cd consul
<!-- 启动consul -->
consul agent -dev
consul agent -server
<!-- 访问consul管理界面 -->
http://localhost:8500
<!-- 指定数据中心启动 -->
consul agent -dev --datacenter=aa
<!-- 推荐配置 -->
path = F:\java\consul
dc1:数据中心
service:当前consul中注册的服务列表
node:用来查看consul中的集群节点
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- consul依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- consul心跳健康检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.properties
# 指定服务端口号
server.port= 8082
# 指定服务名称
spring.application.name=consulClient
# consul server服务注册地址
spring.cloud.consul.host= localhost
# consul server服务默认端口号
spring.cloud.consul.port= 8500
# 之策当前服务的服务名称 默认:${spring.application.name}
spring.cloud.consul.discovery.service-name=${spring.application.name}
开启
consul 服务
@SpringBootApplication
@EnableDiscoveryClient //开启服务注册
public class ConsulClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulClientApplication.class,args);
}
}
服务间通信(负载均衡)
Rest Template
User 模块(端口号:8764)
@RestController
@RequestMapping("user")
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
@GetMapping
public String getMsg(){
log.info("user...");
RestTemplate restTemplate = new RestTemplate();
String forObject = restTemplate.getForObject("http://localhost:8765/order", String.class);
return forObject;
}
}
Order 模块(端口号:8765)
@RestController
@RequestMapping("order")
public class OrdersController {
private static final Logger log = LoggerFactory.getLogger(OrdersController.class);
@GetMapping
public String getMsg(){
log.info("orders...");
return "orders...demo 已执行";
}
}
Ribbon
-
负载均衡的客户端组件
-
实现请求调用时的负载均衡
pom.xml
<!--引入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
application.properties
# 修改用户服务调用订单服务默认负载均衡策略不再使用轮询
orders.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
Ribbon + Rest Template
**(方案一) **使用DiscoveryClient进行服务调用
@Autowired
private DiscoveryClient discoveryClient; //获取DiscoveryClient服务对象
@GetMapping
public String get(){
//通过实例名获取服务集群
List<ServiceInstance> users = discoveryClient.getInstances("orders");
RestTemplate restTemplate = new RestTemplate();
users.forEach(user ->{
log.info("服务名:{},服务路径:{}",user.getServiceId(),user.getUri());
});
//获取示例对应url,拼接请求,返回请求结果
String forObject = restTemplate.getForObject(users.get(0).getUri() + "/order", String.class);
log.info("DiscoveryClient:{}",forObject);
return "ok";
}
(方案二) 使用LoadBalanceClient进行服务调用
@Autowired
private LoadBalancerClient loadBalancerClient; //获取LoadBalancerClient服务对象
@GetMapping
public String get(){
//获取服务
ServiceInstance orders = loadBalancerClient.choose("orders"); //默认轮询
RestTemplate restTemplate = new RestTemplate();
log.info("服务地址:{} 服务主机:{} 服务端口:{}",orders.getUri(),orders.getHost(),orders.getPort());
return restTemplate.getForObject(orders.getUri()+"/order",String.class);
}
**(方案三)**使用LoadBalanced注解进行服务调用
// 使用LoadBalanced注解 作用:可以让对象具有ribbon负载均衡特性
@GetMapping
@LoadBalanced
public String get(){
return restTemplate.getForObject("http://orders/order",String.class);
}
OpenFeign(重点)
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- openfeign客户端组件依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
application.properties
product服务
server.port=8768
spring.application.name=PRODUCT
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
category服务
server.port=8767
spring.application.name=CATEGORY
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
# 配置类别调用商品服务openfeign默认超时时间 默认时间1s(指定某个服务超时时间)
feign.client.config.PRODUCT.connectTimeout = 5000
feign,client.config.PRODUCT.readTimeout = 5000
# 修改openfeign默认调用所有服务超时时间
feign.client.config.default.connectTimeout = 5000
feign.client.config.default.readTimeout = 5000
# 开启feign客户端组件打印日志功能
logging,level.com.ls.feignclient = debug
# 开启openfeign中调用商品服务日志展示类型(请求体参数)
feign.client.config.PRODUCT.loggerLevel = full
feign.client.config.ORDER.loggerLevel = none
开启注解
@SpringBootApplication
@EnableDiscoveryClient //开启服务与注册
@EnableFeignClients //起开feign客户端的调用
public class CategoryApplication {
public static void main(String[] args) {
SpringApplication.run(CategoryApplication.class,args);
}
}
配置接口
@FeignClient("PRODUCT")//服务名称
@RequestMapping("product")
public interface ProductClient {
@GetMapping
String product();
//接口传参test?name=xxx&age=23
@GetMapping("/findOne")
String findOne(@RequestParam("productId") String productId);
//路径传参/test/{id}/{name}
@GetMapping("/test/{id}/{name}")
String test(@PathVariable("id") Integer id,@PathVariable("name") String name);
//对象传参
@GetMapping("/test")
String test(@RequestBody Product product);
//数组传参
@GetMapping("/test")
String test(@requestParam String[] ids);
//集合传参
@GetMapping("/test")
String test(@RequestParam("ids") String[] ids);
//申明返回对象
@GetMapping("/test/{id}")
Product test(@PathVariable("id") Integer id);
}
Controller
ProductController
@RestController
public class ProductController {
private static final Logger log = LoggerFactory.getLogger(ProductController.class);
@Value("${server.port}")
private int port;
//Map集合传参
@GetMapping("/productList")
public Map<String,Object> findByCategoryIdAndPage(Integer page, Integer rows, Integer categoryId){
log.info("当前页: {} 每页显示记录数:{} 当前类别id:{} ",page,rows,categoryId);
//根据类别id分页查询符合当前页集合数据 List<Product> select * from t_product where categoryId=? limt ?(page-1)*rows,?(rows)
//根据类别id查询当前类别下总条数 totalCount select count(id) from t_product where categoryId=?
Map<String, Object> map = new HashMap<>();
List<Product> products = new ArrayList<>();
products.add(new Product(1,"短裙",23.23,new Date()));
products.add(new Product(2,"超短裙",23.23,new Date()));
products.add(new Product(3,"超级超短裙",23.23,new Date()));
int total = 1000;
map.put("rows",products);
map.put("total", total);
return map;
}
//list集合对象传参
@GetMapping("/products")
public List<Product> findByCategoryId(Integer categoryId){
log.info("类别id: {}",categoryId);
//调用业务逻辑根据类别id查询商品列表
List<Product> products = new ArrayList<>();
products.add(new Product(1,"短裙",23.23,new Date()));
products.add(new Product(2,"超短裙",23.23,new Date()));
products.add(new Product(3,"超级超短裙",23.23,new Date()));
return products;
}
//restful传参
@GetMapping("/product/{id}")
public Product product(@PathVariable("id") Integer id){
log.info("id:{}",id);
return new Product(id,"超短连衣裙",23.23,new Date());
}
//集合传参
//springmvc 不能直接接受集合类型参数,如果想要接收集合类型参数必须将集合放入对象中,使用对象的方式接收才行
//oo: oriented(面向) object(对象) 面向对象
// vo(value object): 用来传递数据对象称之为值对象
// dto:(data transfer(传输) object):数据传输对象
@GetMapping("/test4")
public String test4(CollectionVO collectionVO){
collectionVO.getIds().forEach(id-> log.info("id:{} ",id));
return "test4 ok,当前服务端口为: "+port;
}
//数组传参
@GetMapping("/test3")
public String test3(String[] ids){
for (String id : ids) {
log.info("id: {}",id);
}
//手动转为list List<String> strings = Arrays.asList(ids);
return "test3 ok,当前服务端口为: "+port;
}
//对象传参
@PostMapping("/test2")
public String test2(@RequestBody Product product){
log.info("product:{}",product);
return "test2 ok,当前服务端口为: "+port;
}
//路径传参
@GetMapping("/test1/{id}/{name}")
public String test1(@PathVariable("id") Integer id,@PathVariable("name") String name){
log.info("id:{} name:{}",id,name);
return "test1 ok,当前服务端口为: "+port;
}
//零散类型参数接口queryString
@GetMapping("/test")
public String test(String name, Integer age){
log.info("name:{} age:{}",name,age);
return "test ok,当前服务端口为: "+port;
}
@GetMapping("/product")
public String product() throws InterruptedException {
log.info("进入商品服务.....");
//Thread.sleep(2000);
return "product ok,当前提供服务端口:"+port;
}
@GetMapping("/list")
public String list(HttpServletRequest request,String color){
String header = request.getHeader("User-Name");
System.out.println("获取对应请求参数 color: "+color);
System.out.println("获取请求头信息: "+header);
log.info("商品列表服务");
return "list ok当前提供服务端口:"+port;
}
}
CateController
@RestController
@RequestMapping("category")
public class CategoryController {
private static final Logger log = LoggerFactory.getLogger(CategoryController.class);
@Autowired
//获取注入接口对象
private ProductClient productClient;
@GetMapping
public String category(){
log.info("category server ...");
//获取请求返回值
String product = productClient.product();
log.info("服务请求:{}",product);
return "category ok..." + product;
}
}
Hystrix(弹性处理)
熔断
pom.xml
<!-- 已然集成,无需再引入 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
application.properties
#开启openfeign在调用服务过程中,开启hystrix支持, 默认:没有开启
feign.hystrix.enabled=true
开启
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker //开启hystrix服务的熔断功能
public class HystrixApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class,args);
}
}
熔断处理
@RestController
@RequestMapping("hystrix")
public class HystrixController {
@GetMapping
@HystrixCommand(fallbackMethod = "demoFallBack")//熔断之后处理FallBackMethod 书写快速失败方法名
public String demo(Integer id){
System.out.println("demo ok !!!");
if (id<=0){
throw new RuntimeException("无效id!!!!");
}
return "demo ok !!!";
}
public String demoFallBack(Integer id){
return "当前活动过于火爆,服务已经被熔断~";
}
@GetMapping
@HystrixCommand(defaultfallback = "demoFallBack")//熔断之后处理FallBackMethod 书写快速失败方法名
public String demo(Integer id){
System.out.println("demo ok !!!");
if (id<=0){
throw new RuntimeException("无效id!!!!");
}
return "demo ok !!!";
}
}
测试
@RestController
public class DemoController {
//注入openfeign客户端对象
@Autowired
private OpenFeignClient openFeignClient;
@GetMapping("demo")
public String test(){
System.out.println("test ok !!!");
String demoResult = openFeignClient.demo(-1);
System.out.println("demo result :" + demoResult);
return "test ok ~~~";
}
}
OpenFeignClient
//fallback : 这个属性用来指定当前调用服务不可用时,默认的备选处理
@FeignClient(value = "HYSTRIX",fallback = HystrixClientFallBack.class)
public interface OpenFeignClient {
@GetMapping("demo")
String demo(@RequestParam("id") Integer id);
}
默认备选处理
# 自定义OpenFeignClient默认备选处理
@Configuration
public class HystrixClientFallBack implements OpenFeignClient {
@Override
public String demo(Integer id) {
return "当前服务不可用,请稍后再试!id:" +id;
}
}
Hystrix DashBoard
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Hystrix仪表盘 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
application.properties
server.port=8770
spring.application.name=HYSTRIXDASHBOARD
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
开启
# 4.监控的项目中入口类中加入监控路径配置[新版本坑],并启动监控项目
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
gateway(服务网关)
路由转发
pom.xml
<dependency> <!--引入web以来回合gateway发生冲突-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
application.yaml
server:
port: 8771
spring:
application:
name: GATAWAY
cloud:
consul:
host: localhost
port: 8500
gateway:
routes:
- id: cateway_router #路由对象唯一标识
# uri: http://localhost:8767/ #用来类别服务地址 http://localhost:8787/category
uri: lb://CATEGORY # 实现请求的负载均衡 'lb'= 负载均衡
predicates: #断言 用来配置路由规则
- Path=/category/** #基于指定的路径方式请求进行路由
- Method=GET,POST #基于指定的请求方式请求进行路由
- After=2020-07-21T11:39:33.993+08:00[Asia/Shanghai]
- Cookie=username,[A-Za-z0-9]+
- Header=X-Request-Id, \d+
filters:
- AddRequestParameter=id,34
- AddResponseHeader=username,chenyn
- id: product_router
# uri: http://localhost:8768/ #用来类别服务地址 http://localhost:8788/list
uri: lb://PRODUCT # 实现请求的负载均衡
predicates: #断言 用来配置路由规则
- Path=/product/**,/list/**
management:
endpoints:
web:
exposure:
include: "*" #开启所有web端点暴露
- 访问路由管理列表地址
- http://localhost:8989/actuator/gateway/routes
java配置的方式
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("category_router", r -> r.path("/category/**")
.uri("http://localhost:8767/"))
.route("product_router",r -> r.path("/product/**")
.uri("http://localhott:8768"))
.build();
}
}
Config(配置注册中心)
config-server
pom.xml
<dependency> <!--引入web以来回合gateway发生冲突-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
application.yaml
server:
port: 8772
spring:
application:
name: CONFIGSERVER
cloud:
consul:
port: 8500
host: localhost
config:
server:
git:
uri: https://gitee.com/xiaoye_ls/config.git #远端仓库地址
default-label: master
开启
@SpringBootApplication
@EnableConfigServer //开启统一配置中心服务
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
config-client
pom.xml
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--config-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
远端仓库配置
configclient.properties
server.port: 8990
spring.application.name: CONFIGCLIENT
spring.cloud.consul.host: localhost
spring.cloud.consul.port: 8500
spring.profiles.active: dev
configclient-dev.properties
name: zhangsan
configclient-prod.properties
name: xiaosan
远端仓库截图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZtuKNhE-1631424677869)(springcloud开发.assets/image-20210724125938352.png)]
bootstrap.properties
# 告诉当前configclient统一配置中心在注册中心服务id
spring.cloud.config.discovery.service-id = CONFIGSERVER
# 开启当前configclient 根据服务id去注册中心获取
spring.cloud.config.discovery.enabled = true
# 配置注册中心
spring.cloud.consul.host= localhost
spring.cloud.consul.port= 8500
# 获取那个配置文件 1、确定分支 2、确定文件名 3、确定环境
spring.cloud.config.label = master
spring.cloud.config.name = configclient
spring.cloud.config.profile = prod
ConfigController
@RestController
public class ConfigController {
@Value("${name}")
private String name;
@GetMapping("name")
public String getName(){
return name;
}
}
手动刷新远端仓库修改后问配置文件
configController
@RestController
@RefreshScope //刷新域注解 作用:远端仓库被刷新后,自动同步数据
public class ConfigController {
@Value("${name}")
private String name;
@GetMapping("name")
public String getName(){
return name;
}
}
application.properties
#开启所有web端点暴露 [推荐使用这种]
management.endpoints.web.exposure.include=*
发送刷新请求
# 手动调用刷新配置接口
- curl -X POST http://localhost:9099/actuator/refresh
Bus(远端git仓库同步刷新)
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
application.properties
# 统一配置
#连接主机
spring.rabbitmq.host=localhost
#连接mq端口
spring.rabbitmq.port=5672
#连接mq用户名
spring.rabbitmq.username=user
#连接mq密码
spring.rabbitmq.password=password
# 客户端配置
#防止第一次链接不到远程,信息无法获取而导致服务器报错
spring.cloud.config.fail-fast=true
#开启所有web端点暴露 [推荐使用这种]
management.endpoints.web.exposure.include=*
刷新
# 默认情况下使用,类似广播的方式刷新全部配置
curl -X POST http://localhost:7878/actuator/bus-refresh
# 指定端口刷新某个具体服务:
curl -X POST http://localhost:7878/actuator/bus-refresh/configclient:9090
# 指定服务id刷新服务集群节点:
curl -X POST http://localhost:7878/actuator/bus-refresh/configclient
[注意:][configclient代表刷新服务的唯一标识]
springcloud-alibaba
nacos
服务的注册
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入nacos client的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
application.properties
# 端口号
server.port= 8501
# 服务名
spring.application.name= NACOSCLIENT
# nacos客户端配置
spring.cloud.nacos.server-addr= 192.168.1.3:8848
# 作为nacos client注册地址
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
# 指定向nacos server 注册服务名称
spring.cloud.nacos.discovery.service= ${spring.application.name}
SpringBootApplication
@SpringBootApplication
//@EnableDiscoveryClient
public class NacosClientApplication {
public static void main(String[] args) {
SpringApplication.run(NacosClientApplication.class,args);
}
}
远端配置
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入nacos client的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--引入nacos config 依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
boostrap.properties
#Nacos远端地址
spring.cloud.nacos.server-addr=10.235.40.42:8848
#配置组
spring.cloud.nacos.config.group=DEFAULT_GROUP
#配置文件名
#spring.application.name=configclient-prod
spring.cloud.nacos.config.name=configclient
#配置文件后缀
spring.cloud.nacos.config.file-extension=properties
#配置环境
spring.profiles.active=prod
SpringBootApplication
@SpringBootApplication
@RefreshScope
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class,args);
}
}
controller
@Value("${user.name}")
private String username;
@GetMapping("get")
public String getMsg(){
return "远端仓库配置user.name"+ username;
}
远端配置
server.port=8504
spring.application.name=CONFIGCLIENT
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
user.name='liushun'
sentinel
启动sentinel
# linux启动jar
java -jar -Dserver.port=9191 sentinel-dashboard-1.7.2.jar
pom.xml
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
application.properties
server.port= 8505
spring.cloud.nacos.server-addr=192.168.1.6:8848
spring.application.name=SENTINEL
# 开启sentinel保护
feign.sentinel.enabled=true
# 配置sentinel传输端口
spring.cloud.sentinel.transport.dashboard=192.168.1.6:9191
# 指定sentinel组件与sentinel DashBoard 通信端口
spring.cloud.sentinel.transport.port=8719
controller
@RestController
public class DemoController {
private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
@GetMapping("demo")
public String demo(){
logger.info("demo ok!!!");
return "demo ok!!!";
}
}
springcloud小案例
项目结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uci6gvMu-1631424677873)(springcloud开发.assets/image-20210816175513062-1629107715061.png)]
项目依赖
父项目
<?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>org.example</groupId>
<artifactId>springcloud-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud-commons</module>
<module>springcloud-users</module>
<module>springcloud-products</module>
<module>springcloud-gateway</module>
</modules>
<properties>
<spring.cloud.version>Hoxton.SR6</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<!--SpringCloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
用户模块
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--config配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
商品模块
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
网关模块
<dependencies>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
项目功能
用户模块
RestTemplate+Ribbon
@Configuration
public class BeansConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
OpenFeign + Ribbon
@FeignClient("PRODUCTS")
public interface ProductsClient {
@GetMapping("product")
String product();
}
功能实现
# 获取商品
@RestController
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Value("${server.port}")
private Integer port;
//@Autowired
//private RestTemplate restTemplate;
@Autowired
private ProductsClient productsClient;
@GetMapping("invoke")
@SentinelResource("INVOKE")
public String invokeProduct(){
logger.info("invoke product ok !!!");
//String result = restTemplate.getForObject("http://PRODUCTS/product", String.class);
String result = productsClient.product();
logger.info("result:{}",result);
return result;
}
}
主启动类配置
@SpringBootApplication
@EnableFeignClients
@RefreshScope
public class UsersApplication {
public static void main(String[] args) {
SpringApplication.run(UsersApplication.class,args);
}
}
服务集中配置
本地配置
# bootstrap.properties
#Nacos远端地址
spring.cloud.nacos.server-addr=192.168.1.15:8848
#nacos namespace
spring.cloud.nacos.config.namespace=b6c8e7dd-0672-4b2b-8ac7-e71fb7259148
#配置组
spring.cloud.nacos.config.group=USERS
#配置文件名
spring.cloud.nacos.config.name=user
#配置文件后缀
spring.cloud.nacos.config.file-extension=properties
#配置环境
spring.profiles.active=prod
远端配置
# user-prod.properties
# 端口号
server.port= 8888
# 服务名
spring.application.name= USERS
# nacos服务注册中心
spring.cloud.nacos.server-addr= 192.168.1.15:8848
spring.cloud.sentinel.enabled= true
spring.cloud.sentinel.eager= true
spring.cloud.sentinel.transport.port= 8719
spring.cloud.sentinel.transport.dashboard= 192.168.1.15:9191
产品模块
功能实现
@RestController
public class ProductController {
private static final Logger logger = LoggerFactory.getLogger(ProductController.class);
@Value("${server.port}")
private Integer port;
@GetMapping("product")
public String product(){
logger.info("product ok !!!");
return "product ,端口号:" + port;
}
}
主启动类配置
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class,args);
}
}
基础配置
# application.properties
# 端口号
server.port= 9999
# 服务名
spring.application.name= PRODUCTS
# nacos服务注册中心
spring.cloud.nacos.server-addr= 192.168.1.15:8848
网关模块
主启动类
@SpringBootApplication
@RefreshScope
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
服务集中配置
本地配置
# bootstrap.properties
# 远端配置中心
spring.cloud.nacos.server-addr=192.168.1.15:8848
# 配置nacos命名空间
spring.cloud.nacos.config.namespace=b6c8e7dd-0672-4b2b-8ac7-e71fb7259148
# nacos组
spring.cloud.nacos.config.group=GATEWAYS
# 配置文件名
spring.cloud.nacos.config.name=gateways
# 选择生产环境
spring.profiles.active=prod
# 文件后缀名
spring.cloud.nacos.config.file-extension=yaml
服务端配置
# gateways-prod.yaml
server:
port: 8990
spring:
application:
name: GATEWAY
cloud:
nacos:
server-addr: 192.168.1.15:8848
gateway:
routes:
- id: users_route
uri: lb://USERSS
predicates:
- Path=/invoke
- id: product_route
uri: lb://PRODUCTS
predicates:
- Path=/product
类配置
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class,args);
}
}
基础配置
# application.properties
# 端口号
server.port= 9999
# 服务名
spring.application.name= PRODUCTS
# nacos服务注册中心
spring.cloud.nacos.server-addr= 192.168.1.15:8848
网关模块
主启动类
@SpringBootApplication
@RefreshScope
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
服务集中配置
本地配置
# bootstrap.properties
# 远端配置中心
spring.cloud.nacos.server-addr=192.168.1.15:8848
# 配置nacos命名空间
spring.cloud.nacos.config.namespace=b6c8e7dd-0672-4b2b-8ac7-e71fb7259148
# nacos组
spring.cloud.nacos.config.group=GATEWAYS
# 配置文件名
spring.cloud.nacos.config.name=gateways
# 选择生产环境
spring.profiles.active=prod
# 文件后缀名
spring.cloud.nacos.config.file-extension=yaml
服务端配置
# gateways-prod.yaml
server:
port: 8990
spring:
application:
name: GATEWAY
cloud:
nacos:
server-addr: 192.168.1.15:8848
gateway:
routes:
- id: users_route
uri: lb://USERSS
predicates:
- Path=/invoke
- id: product_route
uri: lb://PRODUCTS
predicates:
- Path=/product