• 云原生技术-微服务SpringCloud(1)


    作者简介:2022新星计划第三季云原生与云计算赛道Top5??、华为云享专家??、云原生领域潜力新星??

    ??博客首页:C站个人主页??

    ??作者目的:如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门,共同进步!

    文章目录

    云原生技术-微服务SpringCloud(1)

    搭建提供者、消费者模块

    1:创建一个空Maven项目,删除src目录

    image-20210220134218449

    2:父POM

     
        pom
    
        
            
            Hoxton.RELEASE
    
            2.2.4.RELEASE
    
    
            UTF-8
            UTF-8
            1.8
            10
            10
            UTF-8
    
    
    
        
    
        
    
        
            
            
                
                    org.springframework.cloud
                    spring-cloud-dependencies
                    ${spring.cloud-version}
                    pom
                    import
                
                
                
    
                    org.springframework.boot
                    spring-boot-dependencies
                    ${spring.boot-version}
                    pom
                    import
                
    
    
    
                
                    org.mybatis.spring.boot
                    mybatis-spring-boot-starter
                    1.3.1
                
    
                
                    mysql
                    mysql-connector-java
                    5.1.47
                
    
    
                
                    com.alibaba
                    druid
                    1.0.9
                
    
            
    
    
        
    
    
        
    
            
                
                    src/main/java
                    
                        **/*.xml
                    
                    true
                
            
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    3.创建一个子模块,作微服务的提供者,端口号为8001

    image-20210222004113174

    里面代码如下。。。

    deptController

    @RestController
    public class deptController {
    
        private deptService deptService;
    
        @Autowired
        @Qualifier("deptServiceImpl")
        public void setDeptService(com.boot.service.deptService deptService) {
            this.deptService = deptService;
        }
        @GetMapping(path = "/queryAllDept")
        public List queryAllDept(){
    
    
            return deptService.queryAllDept();
        }
    
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    dao层。deptMapper

    @Mapper //把这个Mapper接口变成可以注入的Bean,*****一定要。
    @Repository  //变成组件  ***一定要
    public interface deptMapper {
    
        List queryAllDept();
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Mapper.xml

    
    
    
    
    
    
        
     
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    service层省略,和普通springBoot项目构建是一样的

    application.yml(8001)

    server:
      port: 8001
    
    spring:
      application:
    #    微服务名
        name: provider_dept8001/8002
      datasource:
        url: jdbc:mysql://localhost:3306/ssmrl?serverTimezone=UTC
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 18420163207
        type: com.alibaba.druid.pool.DruidDataSource
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建一个子模块(springcloud-02-api),专门放实体类

    image-20210222011216901

    public class dept implements Serializable {
    
        private String deptid;
        private String deptName;
    
        public dept() {
        }
    
        public dept(String deptid, String deptName) {
            this.deptid = deptid;
            this.deptName = deptName;
        }
    
        public String getDeptid() {
            return deptid;
        }
    
        public void setDeptid(String deptid) {
            this.deptid = deptid;
        }
    
        public String getDeptName() {
            return deptName;
        }
    
        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }
    
        @Override
        public String toString() {
            return "dept{" +
                    "deptid='" + deptid + ''' +
                    ", deptName='" + deptName + ''' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    创建另外一个子模块,springcloud-02-provider-dept8002

    把springcloud-02-provider-dept8001代码全部复制上去,修改配置文件application.yml(8002)

    server:
      port: 8002
    
    spring:
      application:
    #    微服务名
        name: provider_dept8001/8002
      datasource:
        url: jdbc:mysql://localhost:3306/ssmrl?serverTimezone=UTC
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 18420163207
        type: com.alibaba.druid.pool.DruidDataSource
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为什么我们要复制多一份微服务提供者代码?

    因为考虑到后面我们要使用负载均衡ribbon或者openFeign(不过底层也是ribbon)

    4.创建子模块springcloud-02-comsumer-dept80

    controller层:

    @RestController
    public class deptController80 {
    
        @Autowired
        private RestTemplate restTemplate;
        private final String URL_DEPT="http://localhost:8001/";
    
    
        @GetMapping("/comsumer/queryAllDept")
        public List queryAllDept80(){
            List res = restTemplate.getForObject(URL_DEPT + "queryAllDept", List.class);
    
            return res;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    因为默认的RestTemplate没有放入IOC容器中(也就是没有Bean),我们需要手动的放入IOC容器

    config层

    @Configuration
    public class restTemplateConfig {
    
        @Bean
        public RestTemplate restTemplate(){
    
            return new RestTemplate();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    application.yml(80)

    server:
      port: 80
    
    #
    spring:
      application:
        name: comsumer_dept80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    为什么微服务消费者层的端口是80,因为80端口可以省略不写,就比如我们打开百度,也是不需要写端口号的,因为微服务消费者层是给用户去访问的

    消费者层只需要Controller去远程调用提供者的Controller方法即可,所以消费者层—不能—有dao,service层

    这样提供者和消费者就搭建好了,接下来我们可以引入SpringCloud组件了。。。。。。。


    引入注册中心SpringCloud Eureka

    配置如下:

    image-20210222203000271

    创建子模块springcloud-02-eureka7001(eureka注册中心服务端)

    pom.xml

     
    
            
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
            
                org.springframework.boot
                spring-boot-starter-actuator
            
    
    
    
              
                org.springframework.cloud
                spring-cloud-starter-netflix-eureka-server
            
    
    
    
    
    
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    eureka模块主启动类

    @SpringBootApplication
    @EnableEurekaServer //开启Eureka服务器
    public class SpringBootApplication7001 {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootApplication7001.class,args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    application.yml(7001)

    server:
      port: 7001
    
    
    #  配置eureka
    eureka:
      instance:
        hostname: eureka-server7001.com
      client:
        register-with-eureka: false
        fetchRegistry: false
        service-url:
          defaultZone: http://${eureka.instance.hostname}:7001/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    给提供者springcloud-02-provider-dept8001和8002修改如下

    @SpringBootApplication
    @EnableEurekaClient //eureka客户端
    public class SpringBootApplication8001 {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootApplication8001.class,args);
    
    
        }
    
    }
    
    
    server:
      port: 8001
    
    spring:
      application:
    #    微服务名
        name: provider_dept  
      datasource:
        url: jdbc:mysql://localhost:3306/ssmrl?serverTimezone=UTC
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 18420163207
        type: com.alibaba.druid.pool.DruidDataSource
    
    
    #    eureka Client
    eureka:
      client:
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/
        register-with-eureka: true
        fetch-registry: false
      instance:
        instance-id: eureka-client8001
    
    
    server:
      port: 8002
    
    spring:
      application:
    #    微服务名
        name: provider_dept
      datasource:
        url: jdbc:mysql://localhost:3306/ssmrl?serverTimezone=UTC
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 18420163207
        type: com.alibaba.druid.pool.DruidDataSource
    
    
    #   eureka
    eureka:
      client:
        fetch-registry: false
        register-with-eureka: true
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/
      instance:
        prefer-ip-address: true
        instance-id: eureka-client8002
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    Bug:引入Eureka后报错。

    image-20210222160445890

    。。。取名要规范。。。

    搭建Eureka集群

    创建springcloud-02-eureka7002和7003两个模块

    application.yml(7001)

    server:
      port: 7001
    
    
    #  配置eureka
    eureka:
      instance:
        hostname: eureka-server7001.com
      client:
        register-with-eureka: false
        fetchRegistry: false
        service-url:
          defaultZone: http://eureka-server7002.com:7002/eureka/,http://eureka-server7003.com:7003/eureka/   #集群版就修改这个。单机认自己,集群认其他
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    application.yml(7002)

    server:
      port: 7002
    
    spring:
      application:
        name: eureka7002   #这里可有可无,除了微服务提供者。
    
    eureka:
      instance:
        hostname: eureka-server7002.com
      client:
        fetch-registry: false
        register-with-eureka: false
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/,http://eureka-server7003.com:7003/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    application.yml(7003)

    server:
      port: 7003
    
    spring:
      application:
        name: eureka7003
    
    eureka:
      instance:
        hostname: eureka-server7003.com
      client:
        register-with-eureka: false
        fetch-registry: false
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/,http://eureka-server7002.com:7002/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其实Eureka集群没啥变化,也就是修改了serviceUrl的defaultZone罢了。记住一句话,单机版认自己,集群版认其他

    搭建提供者集群(为了负载均衡)

    在8001和8002微服务中修改defaultZone。

    eureka:
      client:
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/, http://eureka-server7002.com:7002/eureka/, http://eureka-server7003.com:7003/eureka/
    
    • 1
    • 2
    • 3
    • 4

    还有8001和8002的微服务名要一致(spring.application.name)

    spring:
      application:
    #    微服务名
        name: provider-dept  #8001和8002要一致
    
    • 1
    • 2
    • 3
    • 4

    在springcloud-02-comsumer-dept80消费者层

    @Configuration
    public class restTemplateConfig {
    
    
        @Bean
        @LoadBalanced //开启负载均衡
        public RestTemplate restTemplate(){
    
            return new RestTemplate();
        }
    
    
    
    }
    
    
    @SpringBootApplication
    @EnableEurekaClient
    public class SpringBootApplication80 {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootApplication80.class,args);
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    用Ribbon+RestTemplate员工调用提供者的Controller方法

    @RestController
    public class deptController80 {
    
        @Autowired
        private RestTemplate restTemplate;
        private final String URL_DEPT="http://PROVIDER-DEPT/"; //实现负载均衡用提供者微服务名代替IP:Port
    
    
    
        @GetMapping("/comsumer/queryAllDept")
        public List queryAllDept80(){
            List res = restTemplate.getForObject(URL_DEPT + "queryAllDept", List.class);
    
            return res;
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    application.yml(80)

    server:
      port: 80
    
    #
    spring:
      application:
        name: comsumer-dept80
    eureka:
      client:
        fetch-registry: true
        register-with-eureka: false
        service-url:
          defaultZone: http://eureka-server7001.com:7001/eureka/,http://eureka-server7002.com:7002/eureka/,http://eureka-server7003.com:7003/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    Bug:ribbon+restTemplate报错

    image-20210222232329911

    ribbon不支持微服务名有下划线(_),修改过来即可

    spring:
      application:
    #    微服务名
        name: provider-dept
    
    • 1
    • 2
    • 3
    • 4

    使用actuator功能

    #暴露端点。使用actuator功能
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20210222233505528

    Feign/OpenFeign

    创建子模块springcloud-02-comsumer-openFeign-dept80

    所需的依赖

    
           
                org.springframework.cloud
                spring-cloud-starter-openfeign
            
    
    • 1
    • 2
    • 3
    • 4
    • 5

    点进去看看

    image-20210224104302484

    我们可以发现,Feign/openFeign的底层就是Ribbon,所以openFeign自带了负载均衡的功能,相较于Ribbon+restTemplate,openFeign无需手动的使用@LoadBalanced注解来开启负载均衡,而Ribbon需要在restTemplate的Bean上加这个注解才有负载均衡的能力

    主启动类

    @SpringBootApplication
    @EnableFeignClients //开启Feign的客户端支持
    public class springApplicationFeign80 {
    
        public static void main(String[] args) {
    
            SpringApplication.run(springApplicationFeign80.class,args);
    
        }
    
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    编写微服务接口

    @Service
    @FeignClient("PROVIDER-DEPT") //标注这个微服务接口是属于“PROVIDER-DEPT”这个微服务的
    public interface deptService {
        
        //下面的代码直接从微服务提供者的controller复制过来即可
        @GetMapping(path = "/queryAllDept")
        public List queryAllDept();
    
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后便是使用

    @RestController
    public class deptController {
    
        @Autowired
        private deptService deptService;
    
    
        @RequestMapping("/feign/queryAllDept")
        public List queryAllDept(){
    
            return deptService.queryAllDept();
        }
    
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    Bug:OpenFeign调用失败报错405

    错误类型:

    image-20210227163134805

    原因是我们没有在提供者加上@PathVariable或者@RequestParam注解

    解决方法一:在提供者加上@RequestParam注解(每个提供者传入的参数都要加上这个注解)

    @RestController
    public class deptController {
    
        private deptService deptService;
    
        @Value("${server.port}")
        private String port;
    
    
        @Autowired
        @Qualifier("deptServiceImpl")
        public void setDeptService(com.boot.service.deptService deptService) {
            this.deptService = deptService;
        }
    
        @GetMapping(path = "/queryAllDept")
        @HystrixCommand(fallbackMethod = "queryAllDept_Hystrix",commandProperties = {
                @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
                @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
                @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "20000"),//注意这是毫秒。1秒=1000毫秒
                @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50")
    
        })
        public List queryAllDept(@RequestParam("id") String id){
            List depts = deptService.queryAllDept();
            depts.add(new dept("999",port));
            if(Integer.parseInt(id)<0){
                throw new RuntimeException();
            }
    
            return depts;
        }
    
        /**
         * 服务熔断
         */
        public List queryAllDept_Hystrix(@RequestParam("id") String id){
    
            List depts = deptService.queryAllDept();
            depts.add(new dept("1066","Break"));
            return depts;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    修改openFeign的微服务接口

    @Service
    @FeignClient("PROVIDER-DEPT")
    public interface deptService {
        @GetMapping(path = "/queryAllDept")
        public List queryAllDept(@RequestParam("id") String id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    没有报错了!!!

    image-20210227165930130

    解决方法二:在微服务提供者加上@PathVariable注解。。

    省略!!!

    ???本章结束,我们下一章见???

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    leetcode 942. 增减字符串匹配
    新型双功能螯合剂NOTA及其衍生物CAS号:147597-66-8p-SCN-Bn-NOTA
    常见树种(贵州省):009楠木、樟木、桂木种类
    如何策划好一场商直播
    致敬第一个1024(第一次Java代码编程)
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    Android Dialog相关设置
    AlexNet
    【分享】一个神经网络(层数+类型)在线测试 平台
    K8S云计算系列-(3)
  • 原文地址:https://blog.csdn.net/m0_67402970/article/details/126080888