Nacos、Nginx、Feign、Gateway开发思路

开发思路:

一、开发微服务

二、微服务之间通讯

三、微服务集群之间通讯

四、Nacos集群、Nginx(反向代理、负载均衡)

五、客户端通过网关访问微服务

一、开发微服务

服务的开发(https://www.cnblogs.com/WarBlog/p/15348825.html

创建maven项目(父工程、子工程)

      File => New => Project... =>maven

项目结构如图:

父工程依赖配置(负责管理依赖的版本springcloud、MySql、Mybatis)

   注意:所有工程都需要使用springboot,所以将其配置在父工程的配置中 parent 标签

              所有的子工程都需要使用的依赖,就可以通过 dependencies 标签来实现,不需要在每个子工程的pom文件中配置了

 1 <parent>
 2         <artifactId>spring-boot-starter-parent</artifactId>
 3         <groupId>org.springframework.boot</groupId>
 4         <version>2.3.9.RELEASE</version>
 5     </parent>
 6     <properties>
 7         <java.version>1.8</java.version>
 8         <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
 9         <mysql.version>5.1.47</mysql.version>
10         <mybatis.version>2.1.1</mybatis.version>
11     </properties>
12     <dependencyManagement>
13         <dependencies>
14             <!-- springCloud -->
15             <dependency>
16                 <groupId>org.springframework.cloud</groupId>
17                 <artifactId>spring-cloud-dependencies</artifactId>
18                 <version>${spring-cloud.version}</version>
19                 <type>pom</type>
20                 <scope>import</scope>
21             </dependency>
22             <!-- mysql驱动 -->
23             <dependency>
24                 <groupId>mysql</groupId>
25                 <artifactId>mysql-connector-java</artifactId>
26                 <version>${mysql.version}</version>
27             </dependency>
28             <!--mybatis-->
29             <dependency>
30                 <groupId>org.mybatis.spring.boot</groupId>
31                 <artifactId>mybatis-spring-boot-starter</artifactId>
32                 <version>${mybatis.version}</version>
33             </dependency>
34         </dependencies>
35     </dependencyManagement>
36     <dependencies>
37         <dependency>
38             <groupId>org.projectlombok</groupId>
39             <artifactId>lombok</artifactId>
40         </dependency>
41     </dependencies>
View Code

子工程的依赖配置

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
View Code

创建子工程中类

启动类

@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class,args);
    }
}
View Code

配置(配置数据库连接)、Controller、Service、Mapper、POJO

配置application.yaml(配置服务器端口、数据库连接、mybatis)

server:
  port: 8081 #微服务的端口
spring:
  datasource:
    url: jdbc:mysql://192.168.223.129:3306/cloud-user?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  type-aliases-package: com.xxx.pojo
  configuration:
    map-underscore-to-camel-case: true
View Code

POJO

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
View Code

Mapper

@Mapper
public interface UserMapper {
    @Select("select * from tb_user where id = #{id}")
    User findById(@Param("id") Long id);
}
View Code

Service

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id){
        return userMapper.findById(id);
    }
}
View Code

Controller

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User queryByid(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}
View Code

启动出现异常

com.mysql.jdbc.Driver 对应 mysql-connector-java 5版本
com.mysql.cj.jdbc.Driver 对应 mysql-connector-java 6 版本

访问路径:http://localhost:8081/user/2

可以看到user的微服务已经可以访问到了,order的微服务开发和user类似

POJO

import lombok.Data;

@Data
public class Order {
    private long id;
    private long user_id;
    private String name;
    private long price;
    private int num;
    private User user;
}
View Code

OrderService

 1 @Service
 2 public class OrderService {
 3     @Autowired
 4     private OrderMapper orderMapper;
 5 
 6     public Order queryById(long id)
 7     {
 8         return orderMapper.findById(id);
 9     }
10 }

访问地址:http://localhost:8082/order/101

访问成功了

下载链接:https://pan.baidu.com/s/1sQb3gjKO98bQwjKg_iXBpA提取码:ny1i

user的数据是null,微服务之间通讯如何完成???以通过RestTemplate实现

 二、微服务之间通讯

    @Autowired
    private RestTemplate restTemplate;

    public Order queryById(long id)
    {
        Order order = orderMapper.findById(id);
        String url="http://localhost:8081/user/"+order.getUserId();
        User user=restTemplate.getForObject(url,User.class);
        order.setUser(user);
        return order;
    }

注意:mybatis默认是属性名和数据库字段名一一对应的,即 数据库表列:user_name 实体类属性:user_name

map-underscore-to-camel-case: true 使用驼峰命名 数据库表列:user_name 实体类属性:userName

访问Order微服务:http://localhost:8082/order/103

链接:https://pan.baidu.com/s/1ij1t7e0-jBgt_9aLHHM_2Q 提取码:peec

 

三、微服务集群之间通讯

如果Order微服务访问的User服务有多个服务怎么办??

开启多个服务

 

现在两个User微服务怎么能被访问到

Nacos(https://www.cnblogs.com/WarBlog/p/15398490.html)

 父工程pom文件添加依赖管理

<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
View Code

子工程pom文件添加依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
View Code

application.yaml配置Nacos

user微服务

spring:
  application:
    name: userservice
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务端地址
View Code

order微服务

spring:
  application:
    name: orderservice
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务端地址
View Code

启动类中的RestTemplate需要添加@LoadBalanced(@LoadBalanced 的原理:对请求地址进行替换,或者根据具体的负载策略选择服务地址,然后再去调用)

@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }

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

 

访问Nacos(http://127.0.0.1:8848/nacos/)

重启微服务

修改Order微服务的service层

    @Autowired
    private RestTemplate restTemplate;

    public Order queryById(long id)
    {
        Order order = orderMapper.findById(id);
        String url="http://userservice/user/"+order.getUserId();
        User user=restTemplate.getForObject(url,User.class);
        order.setUser(user);
        return order;
    }

访问Order服务(http://localhost:8082/order/101)

链接:https://pan.baidu.com/s/1tVVWTY8sGHg7Oiw-xjGGcw 提取码:3y8s

这个就可以实现微服务集群之间通讯但是RestTemplate的Url是硬编码的,可以使用Feign来完善

Feign(https://www.cnblogs.com/WarBlog/p/15419369.html)

Order微服務添加Feign依賴

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

开启Feign

@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}

编写Feign客户端

 

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

将RestTemplate改为Feign的远程调用

    @Autowired
    private UserClient userClient;

    public Order queryById(long id)
    {
        Order order = orderMapper.findById(id);
        User user = userClient.findById(order.getUserId());
        order.setUser(user);
        return order;
    }
View Code

访问 http://localhost:8082/order/101

链接:https://pan.baidu.com/s/1I4Stk4__6dyY2m0XHxzUXg 提取码:ghgc

Feign优化

连接池配置

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

Order微服务

feign:
  client:
    config:
      default:
        loggerLevel: Full
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

FeignClient抽取为独立模块

添加依赖

        <dependency>
            <groupId>com.xxx</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

访问http://localhost:8082/order/104

链接:https://pan.baidu.com/s/1rh_4Xw3olSyUCQpA0bINiw 提取码:v9sc

 

上图内容已经全部实现,这样所有请求都是需要依赖Nacos来完成的,如果Nacos服务器失效的话,所有的服务就无法相应,这时就需要Nacos集群

四、Nacos集群和Nginx(https://www.cnblogs.com/WarBlog/p/15410601.html)

访问 http://localhost:8082/order/103

 

链接:https://pan.baidu.com/s/1_WZ1fg88I-fwSOeSYCrZMQ 提取码:qfqo

客户端可以直接访问微服务,真实微服务开发中,不可能是任何人都可以访问所有微服务,就要在访问微服务之前,添加一些过滤和认证授权的功能

五、客户端通过网关(Gateway)访问(https://www.cnblogs.com/WarBlog/p/15428522.html)

1、配置gateway的路由过滤器添加请求头信息

2、配置默认过滤器(default-filters)对所有路由请求头添加信息

spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:80 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,判断请求是否符合路由规则
            - Path=/user/** # 按照路径匹配,只要以/user/开头就符合要求
          filters:
            - AddRequestHeader=info, route filter
        - id: order-service # 路由id,自定义,只要唯一即可
          uri: lb://orderservice1 # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,判断请求是否符合路由规则
            - Path=/order/** # 按照路径匹配,只要以/user/开头就符合要求
      default-filters:
        - AddRequestHeader=info, default filter
View Code

3、通过全局过滤器(GlobalFilter)请求身份验证

@Order(-1)
@Component
public class AuthorizationFilter implements GlobalFilter{
    @Override
    public 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();
    }
}
View Code

修改OrderController和UserController读取请求头信息

    @GetMapping("/{id}")
    public Order queryByid(@PathVariable("id") long id,
                           @RequestHeader(value = "Info",required = false) String info)
    {
        System.out.println(info);
        return orderService.queryById(id);
    }
View Code

访问 http://localhost:10018/order/101?authorization=admin

 

访问 http://localhost:10018/user/1?authorization=admin

链接:https://pan.baidu.com/s/1mdvL3wlsmZtvMsmnpExbuA 提取码:zo3d

 

posted @ 2022-10-19 16:06  一杯水M  阅读(1280)  评论(0编辑  收藏  举报