SpringCloud学习笔记(五、视图微服务-RIBBON)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: SpringCloud学习笔记(五、视图微服务-RIBBON)

RIBBON是什么?

前面已经做好了数据微服务,现在是时候整个视图微服务访问前面注册好的数据微服务了。 springcloud 提供了两种方式,一种是 Ribbon,一种是 Feign。

Ribbon 是使用 restTemplate 进行调用,并进行客户端负载均衡。 什么是客户端负载均衡呢? 在前面 注册数据微服务  里,注册了8001和8002两个微服务, Ribbon 会从注册中心获知这个信息,然后由 Ribbon  这个客户端自己决定是调用哪个,这个就叫做客户端负载均衡。

Feign 是什么呢? Feign 是对 Ribbon的封装,调用起来更简单。

建立子项目

创建子项目 product-view-service-ribbon:

image.png

pom.xml

spring-cloud-starter-netflix-eureka-client: eureka 客户端

spring-boot-starter-web: springmvc

spring-boot-starter-thymeleaf: thymeleaf 做服务端渲染

<?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">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>edu.hpu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>product-view-service-ribbon</artifactId>
    <name>product-view-service-ribbon</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>  <!--eureka 客户端-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>  <!--SpringMvc-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>
</project>
实体类
package edu.hpu.springcloud.pojo;
public class Product {
    private int id;
    private String name;
    private int price;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    public Product(int id, String name, int price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
    public Product() {
    }
}
Ribbon 客户端

Ribbon 客户端, 通过 restTemplate 访问 http://PRODUCT-DATA-SERVICE/products , 而 product-data-service 既不是域名也不是ip地址,而是 数据服务在 eureka 注册中心的名称。

看一下注册中心:

image.png上面那个地址只指定了服务,没有指定端口号。

package edu.hpu.springcloud.client;
import edu.hpu.springcloud.pojo.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.List;
//Ribbon 客户端
@Component
public class ProductClientRibbon {
    @Autowired
    RestTemplate restTemplate;
    public List<Product> listProcucts(){
        return restTemplate.getForObject("http://PRODUCT-DATA-SERVICE/products",List.class);
    }
}
服务层

服务层数据从客户端获取

package edu.hpu.springcloud.service;
import edu.hpu.springcloud.client.ProductClientRibbon;
import edu.hpu.springcloud.pojo.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
    @Autowired
    ProductClientRibbon productClientRibbon;
    public List<Product> listProducts(){
        return productClientRibbon.listProcucts();   //从productClientRibbon中获得数据服务
    }
}
控制层
package edu.hpu.springcloud.controller;
import edu.hpu.springcloud.pojo.Product;
import edu.hpu.springcloud.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class ProductController {
    @Autowired
    ProductService productService;
    @RequestMapping("/products")
    public Object products(Model m){
        List<Product> ps=productService.listProducts();
        m.addAttribute("ps",ps);
        return "products";
    }
}
视图

视图采用thymeleaf:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>products</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style>
        table {
            border-collapse:collapse;
            width:400px;
            margin:20px auto;
        }
        td,th{
            border:1px solid gray;
        }
    </style>
</head>
<body>
<div class="workingArea">
    <table>
        <thead>
        <tr>
            <th>id</th>
            <th>产品名称</th>
            <th>价格</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="p: ${ps}">
            <td th:text="${p.id}"></td>
            <td th:text="${p.name}"></td>
            <td th:text="${p.price}"></td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>
配置

application.yml,eureka server 的地址,以及自己的名称。 另外是一些 thymeleaf 的默认配置

eureka:
  clg: UTF-8
    content-type: text/html
    mode: HTML5ient:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: product-view-service-ribbon
  thymeleaf:
    cache: false
    prefix: classpath:/templates/
    suffix: .html
    encodin
启动类

ProductDataServiceApplication,

启动类, 注解多了个 @EnableDiscoveryClient, 表示用于发现eureka 注册中心的微服务。

还多了个 RestTemplate,就表示用 restTemplate 这个工具来做负载均衡

   @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

在ribbon客户端中使用了这个RestTemplate.

package edu.hpu.springcloud;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NetUtil;
import cn.hutool.core.util.NumberUtil;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@SpringBootApplication
@EnableEurekaClient
public class ProductDataServiceApplication {
    public static void main(String[] args) {
        int port = 0;
        int defaultPort = 8003;
        Future<Integer> future = ThreadUtil.execAsync(() ->{
            int p = 0;
            System.out.println("请于5秒钟内输入端口号, 推荐  8001 、 8002  或者  8003,超过5秒将默认使用 " + defaultPort);
            Scanner scanner = new Scanner(System.in);
            while(true) {
                String strPort = scanner.nextLine();
                if(!NumberUtil.isInteger(strPort)) {
                    System.err.println("只能是数字");
                    continue;
                }
                else {
                    p = Convert.toInt(strPort);
                    scanner.close();
                    break;
                }
            }
            return p;
        });
        try{
            port=future.get(5, TimeUnit.SECONDS);
        }
        catch (InterruptedException | ExecutionException | TimeoutException e){
            port = defaultPort;
        }
        if(!NetUtil.isUsableLocalPort(port)) {
            System.err.printf("端口%d被占用了,无法启动%n", port );
            System.exit(1);
        }
        new SpringApplicationBuilder(ProductDataServiceApplication.class).properties("server.port=" + port).run(args);
    }
}
运行访问

image.png

调用图示

这里面三个角色,注册中心、服务提供者、服务消费者,数据微服务作为服务提供者,视图微服务作为服务消费者。

1、 首先数据微服务和视图微服务都被 eureka 管理起来了。

2、 数据服务是由三个实例的集群组成的,端口分别是 8001 , 8002,8003。

3、视图微服务通过 注册中心调用微服务, 然后负载均衡到 8001 、8002或者8003端口的应用上。

image.png

错误

1、springCloud com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect

在默认设置下,Eureka服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为。

禁止方式如下:在application.properties配置文件中增加以下内容

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

.yml也差不多,写的时候注意级别就行了。

2、低级错误:注册中心和数据微服务没启动

中间关了IJ,直接启动视图微服务,爆了一堆错,一想,是注册中心和数据微服务没启动,它向谁请求、调用谁去。

3、java.lang.IllegalStateException: No instances available for PRODUCT-DATA-SERVICE

找不到这个实例,我们看一下注册中心,看看数据微服务叫什么名字。

image.png似乎也没什么错,不算了,直接给它粘贴到客户端。OK。

4、java.net.ConnectException: Connection refused: connect

刷新页面的时候发现报了这么个错误,负载均衡一到数据微服务8002这个端口的时候就报错,似乎是被占用了吧,我又注册个端口为8003的数据微服务,这个端口倒是没有问题。

image.png

参考:

【1】、http://how2j.cn/k/springcloud/springcloud-ribbon/2040.html#nowhere

【2】、https://blog.csdn.net/qq_39930369/article/details/87616077

【3】、https://www.cnblogs.com/zmblog/p/8777878.html


相关实践学习
小试牛刀,一键部署电商商城
SAE 仅需一键,极速部署一个微服务电商商城,体验 Serverless 带给您的全托管体验,一起来部署吧!
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
3月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
222 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
2月前
|
搜索推荐 NoSQL Java
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
139 17
|
1月前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
2月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
120 7
|
3月前
|
Java Nacos Sentinel
Spring Cloud Alibaba:一站式微服务解决方案
Spring Cloud Alibaba(简称SCA) 是一个基于 Spring Cloud 构建的开源微服务框架,专为解决分布式系统中的服务治理、配置管理、服务发现、消息总线等问题而设计。
716 13
Spring Cloud Alibaba:一站式微服务解决方案
|
3月前
|
Java 关系型数据库 Nacos
微服务SpringCloud链路追踪之Micrometer+Zipkin
SpringCloud+Openfeign远程调用,并用Mircrometer+Zipkin进行链路追踪
439 20
|
2月前
|
Java 关系型数据库 数据库
微服务SpringCloud分布式事务之Seata
SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程
145 1
|
22天前
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
212 1
|
6月前
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
2月前
|
人工智能 安全 Java
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
241 4

热门文章

最新文章