欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > SpringCloud基础学习

SpringCloud基础学习

2025/5/15 16:21:12 来源:https://blog.csdn.net/2301_78630849/article/details/145963573  浏览:    关键词:SpringCloud基础学习

SpringCloud

private RestTemplate restTemplate;//提供多种边界访问远程http服务的方法,简单的Restful服务模板
//(url,实体:Map,Class<T> responseType)
​
@Autowired
private RestTemplate restemplate;
​
private static final String REST_URL_PREFIX = "http://localhost:8081";
​
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}

1.Ribbon

Ribbon负载均衡

负载均衡策略,通过定义IRule可以修改负载均衡规则,有两种方式

  1. 代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:

    @Bean
    public IRule randomRule(){return new RandomRule();
    }
    //针对全局
  2. 配置文件方式:在order-service的application.yml文件中,添加新的配置也能修改规则

    userservice:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    //针对某个微服务

Ribbon饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启

ribbon:eager-load:enabled: true # 开启饥饿加载clients: userservice # 指定对userservice这个服务饿加载

2.Nacos

注册中心

服务注册

  1. 启动微服务

  2. 引入服务发现依赖

  3. 配置Nacos地址

  4. 查看注册中心效果

  5. 集群模式启动测试

服务集群属性

spring:cloud:nacos:server-addr: localhost:8848 # nacos服务端地址discovery: cluster-name: HZ # 配置集群名称,也就是机房位置

服务发现

  1. 开启服务发现功能 @EnableDiscoveryClient

  2. 测试服务发现AI

@SpringBootTest
public class DiscoveryTest {
​@AutowiredDiscoveryClient discoveryClient;
​@Testvoid discoveryClientTest(){for (String service : discoveryClient.getServices()){System.out.println("service = " + service);//获取ip+端口List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {System.out.println("ip:"+instance.getHost()+";"+"port = "+ instance.getPort());}}}
}

负载均衡

  1. 引入负载均衡依赖 spring-cloud-starter-localbalancer

  2. 测试负载均衡API LoadBalancerClient

  3. 测试远程调用 RestTemplate

  4. 测试负载均衡调用 @LoadBalanced

// 完成负载均衡的发送请求
private Product getProductFromRemoteWithLoadBalance(Long productId){//1.获取到商品服务所在的所有机型IP+portServiceInstance choose = loadBalancerClient.choose("service-product");//远程URLString url = "http://"+choose.getHost()+":"+choose.getPort()+"/product/"+productId;log.info("远程请求:{}",url);//2.给远程发送请求Product product = restTemplate.getForObject(url,Product.class);return product;
}

也可以将@LoadBalanced写到远程调用客户端上,也可以实现负载均衡

// 基于注解负载均衡的发送请求
private Product getProductFromRemoteWithLoadBalance(Long productId){String url = "http://service-product/product/"+productId;//2.给远程发送请求 service-product会被动态替换Product product = restTemplate.getForObject(url,Product.class);return product;
}

如果注册中心宕机,远程调用还能成功嘛 两种情况,是否调用过

服务实例的权重设置

  1. 在Nacos控制台可以设置实例的权重值,首先选中实例后面的编辑按钮

  2. 将权重设置为0.1,测试可以发现8081被访问到的频率大大降低

环境隔离

Nacos中服务存储 和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离

修改order-service的application.yml,添加namespace:

spring:datasource:url: jdbc:mysql://localhost:3306/zkw?useSSL=falsenamespace: rootpassword: 123456driver-class-name: com.mysql.jdbc.Drivercloud:nacos:server-addr: localhost:8848discovery:cluster-name: SH # 上海namespace: # 命名空间
配置中心

设置 配置文件的id:[服务名称]-[profile].[后缀名]

基本使用

  1. 启动Nacos

  2. 引入依赖

    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
  3. 在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件

    spring:application:name: userservice # 服务名称profiles:active: dev # 开发环境cloud:nacos:server-addr: localhost:8848 # Nacos地址config:file-extension: yaml # 文件后缀名
  4. 创建data-id(数据集)

动态刷新

  1. @Value("${xx}")获取配置 + @RefreshScope 实现自动刷新

  2. @ConfigurationProperties 无感自动刷新

  3. NacosConfigManager 监听配置变化

Nacos中的数据集和application.properties有相同的配置,哪个会生效?

先导入优先,外部优先

nacos集群搭建

3.Feign

Feign是一个声明式的http客户端

定义和使用Feign客户端

  1. 引入依赖

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
    <dependency>
  2. 在order-service的启动类添加注解并开启Feign的功能

    @EnableFeiClients
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {public static void main(String[] args){SpringApplication.run(OrderApplication.class, args);}
    }
  3. 编写Feign客户端

    @FeignClient("userservice")
    public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
    }

    主要是基于SpringMVC的注解来声明远程调用信息

Feign自定义配置

配置Feign日志有两种方式:

方式一:配置文件方式

  1. 全局生效:

    feign:client:config:default: #这里用default就是全局配置,如果是写服务器名称,则是针对某个微服务的配置loggerLevel: FULL #日志级别
  2. 局部生效

    feign:client:config:userservice:loggerLevel: FULL

方式二:java代码方式,需要先声明一个Bean

public class FeignClientConfiguration{@Beanpublic Logger.Level feignLogLevel(){return Logger.level.BASIC;}
}
  1. 全局配置:则把它放到@EnableFeignClients这个注解中

    @EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
  2. 局部配置:则把它反到@FeignClient这个注解中

    @FeignClients(value = "userservice",configuration = FeignClientConfiguration.class)

Feign性能优化

Feign底层实现:

  • URLConnection:默认实现,不支持连接池

  • Apache HttpClien:支持连接池

  • OKHttp:支持连接池

因此性能优化主要包括:

  1. 使用连接池代替默认的URLConnection

  2. 日志级别,最好用basic或none

性能优化-连接池配置

1.引入依赖

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

2.配置连接池

feign:client:config:default:loggerLevel: BASIChttpclient:enable: truemax-connections: 200 #最大连接数max-connections-per-route:50 #mei'ge

Feign的最佳实践

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准

public interface UserAPI{@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}
​
----------------------------------------------@FeignClient(value = "userservice")
public interface UserClient extend UserAPI{
}
​
----------------------------------------------@RestController
public class UserController implements UserAPI{
}

方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

  1. 首先创建一个module,命为feign-api,然后引入feign的starter依赖

  2. 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

  3. 在order-service中引入feign-api的依赖

  4. 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包

  5. 重启测试

4.网关

网关功能:

  • 身份认证和权限校验

  • 服务路由、负载均衡

  • 请求限流

搭建网关服务

  1. 创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖

    <!--网关依赖-->
    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--nacos服务发现依赖-->
    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
  2. 编写路由配置及nacos地址

    server:port: 10010 # 网管端口
    spring:application:name: getway # 服务名称cloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由id,自定义,只要唯一即可# uri: 路由的目标地址 http就是固定地址uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称predicates: # 路由断言,也就是判断请求是否符合路由规则的条件- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

路由断言工厂

网关路由可以配置的内容包括:

  • 路由id:路由唯一标识

  • uri:路由目的地,支持lb和http两种

  • predicates:路由断言,盘软请求是否符合要求,符合则转发到路由目的地

  • filters:路由过滤器,处理请求或响应

路由的过滤器配置

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回 的响应做处理

给所有进入userservice的请求添加一个请求头

实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器

spring:cloud:gateway:routes: #网关路由配置- id: userserviceuri: lb://userservicepredicates:- Path=/user/**filters: #过滤器- AddRequestHeader=Truth,Itcast is freaking awesome! #添加请求头

要对所有的路由都生效,则可以将过滤器工厂写道default下

spring:application:name: gateway #服务名称cloud:nacos:server-addr: localhost:8848 #nacos地址gateway:routes: #网关路由配置- id: userserviceuri: lb://userservicepredicates:- Path=/user/**- id: order-serviceuri: lb://orderservicepredicates:- Path=/order/**default-filters: #默认过滤器,会对所有的路由请求都生效- AddRequestHeader=Truth,Itcast is freaking awesome! 

全局过滤器 GlobalFilter

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样定定义方式是实现GlobalFilter接口

@Order(-1)
@Component
public interface GlobalFilter {/*** 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器**@param exchange 请求上下文,里面可以获取Request、Response信息*@param chain 用来把请求委托给下一个过滤器*@return {@code Mono<void>} 返回标示当前过滤器业务结束*/@OverrideMono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//1.获取请求参数ServerHttpRequest request = exchange.getRequest();MultiValueMap<String,String> params = request.getQueryParams();//2.获取请求参数中的 authorization 参数String auth = params.getFirst("authorization");//3.判断参数值是否等于adminif("admin".equals(auth)){//4.是,放行return chain.filter(exchange);}//5.否,拦截//5.1 设置状态码exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//5.2 拦截请求return exchange.getResponse().setComplete();}
}

过滤器链执行顺序

每个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前;其中GlobalFilter由我们指定,路由过滤器和defaultFilter的order则是由Spring指定,默认是按照声明顺序从1开始

当过滤器的order值一样时 defaultFilter > 路由过滤器 > GlobalFilter

跨域问题处理

网关处理跨域采用的是CORS方案

spring:cloud:gateway:globalcors: #全局的跨域处理add-to-simple-url-handler-mapping: true #解决options请求被拦截问题corsConfigurations:'[/**]':allowedOrigins: #允许哪些网站的跨域请求- "http://localhost:8090"- "http://www.leyou.com"allowedMethods: #允许的跨域ajax请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" #允许在请求中携带的头信息allowCredentials: true #是否允许携带cookiemaxAge: 36000 #这次跨域检测的有效期

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词