主页 > 游戏开发  > 

SpringCloud基础学习

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可以修改负载均衡规则,有两种方式

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

@Bean public IRule randomRule(){    return new RandomRule(); } //针对全局

配置文件方式:在order-service的application.yml文件中,添加新的配置也能修改规则

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

Ribbon饥饿加载

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

ribbon: eager-load:   enabled: true # 开启饥饿加载   clients: userservice # 指定对userservice这个服务饿加载 2.Nacos 注册中心

服务注册

启动微服务

引入服务发现依赖

配置Nacos地址

查看注册中心效果

集群模式启动测试

服务集群属性

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

服务发现

开启服务发现功能 @EnableDiscoveryClient

测试服务发现AI

@SpringBootTest public class DiscoveryTest { ​    @Autowired    DiscoveryClient discoveryClient; ​    @Test    void 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());           }       }   } }

负载均衡

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

测试负载均衡API LoadBalancerClient

测试远程调用 RestTemplate

测试负载均衡调用 @LoadBalanced

// 完成负载均衡的发送请求 private Product getProductFromRemoteWithLoadBalance(Long productId){    //1.获取到商品服务所在的所有机型IP+port    ServiceInstance choose = loadBalancerClient.choose("service-product");    //远程URL    String 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; }

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

服务实例的权重设置

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

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

环境隔离

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

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

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

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

基本使用

启动Nacos

引入依赖

<dependency>    <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>

在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件

spring: application:   name: userservice # 服务名称 profiles:   active: dev # 开发环境 cloud:   nacos:     server-addr: localhost:8848 # Nacos地址     config:       file-extension: yaml # 文件后缀名

创建data-id(数据集)

动态刷新

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

@ConfigurationProperties 无感自动刷新

NacosConfigManager 监听配置变化

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

先导入优先,外部优先

nacos集群搭建

3.Feign

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

定义和使用Feign客户端

引入依赖

<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-openfeign</artifactId> <dependency>

在order-service的启动类添加注解并开启Feign的功能

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

编写Feign客户端

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

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

Feign自定义配置

配置Feign日志有两种方式:

方式一:配置文件方式

全局生效:

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

局部生效

feign: client:   config:     userservice:       loggerLevel: FULL

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

public class FeignClientConfiguration{  @Bean  public Logger.Level feignLogLevel(){    return Logger.level.BASIC; } }

全局配置:则把它放到@EnableFeignClients这个注解中

@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)

局部配置:则把它反到@FeignClient这个注解中

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

Feign性能优化

Feign底层实现:

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

Apache HttpClien:支持连接池

OKHttp:支持连接池

因此性能优化主要包括:

使用连接池代替默认的URLConnection

日志级别,最好用basic或none

性能优化-连接池配置

1.引入依赖

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

2.配置连接池

feign: client:   config:     default:       loggerLevel: BASIC httpclient:   enable: true   max-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配置都放到这个模块中,提供给所有消费者使用

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

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

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

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

重启测试

4.网关

网关功能:

身份认证和权限校验

服务路由、负载均衡

请求限流

搭建网关服务

创建新的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>

编写路由配置及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: userservice         uri: lb://userservice         predicates:           - Path=/user/**         filters: #过滤器           - AddRequestHeader=Truth,Itcast is freaking awesome! #添加请求头

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

spring: application:   name: gateway #服务名称 cloud:   nacos:     server-addr: localhost:8848 #nacos地址   gateway:     routes: #网关路由配置       - id: userservice         uri: lb://userservice         predicates:           - Path=/user/**       - id: order-service         uri: lb://orderservice         predicates:           - 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>} 返回标示当前过滤器业务结束     */    @Override    Mono<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.判断参数值是否等于admin        if("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:// .leyou "           allowedMethods: #允许的跨域ajax请求方式             - "GET"             - "POST"             - "DELETE"             - "PUT"             - "OPTIONS"           allowedHeaders: "*" #允许在请求中携带的头信息           allowCredentials: true #是否允许携带cookie           maxAge: 36000 #这次跨域检测的有效期
标签:

SpringCloud基础学习由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“SpringCloud基础学习