0
点赞
收藏
分享

微信扫一扫

微服务笔记01

young_d807 2022-03-11 阅读 32

草稿,还需后期整理

01. 微服务架构

什么是微服务?

image-20220117132138631

主题词01:95后数字化生活-落地维度

主题词02:分布式微服务架构-落地维度

image-20220117133141848

02. springCloud简介

是什么

SpringCloud = 分布式为服务架构一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶

image-20220117133848450

京东

image-20220117134135915

阿里

image-20220117134206550


image-20220117134328297


image-20220117134531229


image-20220117134545397


image-20220117134730003

符合微服务技术维度


上篇:springboot2.x和springcloud H

版本对应

image-20220117140013134


image-20220117141749123

03. 支付模块

1. 环境搭建

image-20220117143052026


隐藏.idea文件夹

image-20220117173210469


  1. maven构建一个父工程:
    • image-20220117143250420
  • 导入依赖

    • <!-- 统一管理jar包版本 -->
          <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <maven.compiler.source>1.8</maven.compiler.source>
              <maven.compiler.target>1.8</maven.compiler.target>
              <junit.version>4.12</junit.version>
              <log4j.version>1.2.17</log4j.version>
              <lombok.version>1.18.12</lombok.version>
              <mysql.version>5.1.47</mysql.version>
              <druid.version>1.1.16</druid.version>
              <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
          </properties>
      
          <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version  -->
          <dependencyManagement>
              <dependencies>
                  <!--spring boot 2.2.2-->
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-dependencies</artifactId>
                      <version>2.2.2.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <!--spring cloud Hoxton.SR1-->
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>Hoxton.SR1</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <!--spring cloud alibaba 2.1.0.RELEASE-->
                  <dependency>
                      <groupId>com.alibaba.cloud</groupId>
                      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                      <version>2.1.0.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                      <version>${mysql.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>com.alibaba</groupId>
                      <artifactId>druid</artifactId>
                      <version>${druid.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.mybatis.spring.boot</groupId>
                      <artifactId>mybatis-spring-boot-starter</artifactId>
                      <version>${mybatis.spring.boot.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>${junit.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>log4j</groupId>
                      <artifactId>log4j</artifactId>
                      <version>${log4j.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <version>${lombok.version}</version>
                      <optional>true</optional>
                  </dependency>
              </dependencies>
          </dependencyManagement>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-maven-plugin</artifactId>
                      <configuration>
                          <fork>true</fork>
                          <addResources>true</addResources>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      

dependencyManagement与dependencies的区别


所以啊,你在使用dependencyManagement包住dependencies之后,就会发现,我们的依赖里面根本就没有导入这些依赖,我觉得吧这些就是起到限定作用,导入还是需要你在子项目中导入才行。



maven中如何跳过单元测试

image-20220117170042781


父工程创建完成执行mvn:install将父工程发布到仓库方便子工程继承

image-20220117170343030

创建微服务模块步骤

image-20220117172915075


自行深入探索springboot的web,actuator

image-20220117175658090

这两个依赖要一起出现

写业务代码

vue-controller-service-dao-mysql

我们从后面向前推进

implements Serializable的作用

image-20220117181842891

pojo层基本数据类型为什么要包装类好

@Resource是java自带的

@Autowired是spring的

useGeneratedKeys=“true” keyProperty="id"的用法

上面用法

mybatis代码细品

<resultMap id="BaseResultMap" type="com.lin.entities.Payment">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>

<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO payment(`serial`) VALUES(#{serial});
</insert>

<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap" >
    SELECT * FROM payment WHERE id=#{id};
</select>
  • resultMap能够帮助我们将mysql查询结果返回元素映射到我们一个对象上面,然后完成属性一 一映射

  • useGeneratedKeys=“true” keyProperty="id"这个上面介绍了,就不讲了

设置返回码

if (result > 0) {
    return new CommonResult(200, "插入数据库成功", result);
} else {
    return new CommonResult(444, "插入数据库失败", null);
}
  • 200:表示插入成功
  • 444:表示插入失败

postman发请求

image-20220117220059726

Run DashBoard

image-20220117222133206


上面这个方法已经对我的idea没有用了

这篇文章可以

  1. image-20220118144244963
  2. image-20220118144253521
  3. 点击加号之后,选择springboot就可以了

04. 热部署Devtools


05. 订单模块

RestTemplate

使用方法
常用方法

image-20220118001114610

工程重构

将两个类的entities的相同类抽取出来

cn.hutool

gitee开源代码

使用方法

maven命令clean install

06. Eureka学习

什么是服务治理

​ Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理

什么是服务注册与发现

Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))

image-20220118120819170


Eureka包含两个组件:Eureka Server和Eureka Client

1、Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。

2、EurekaClient通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

Eureka Server构建

  1. 创建一个基础项目

  2. 改pom

    • <dependencies>
          <!--eureka-server-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
          </dependency>
          <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
          <dependency>
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!--boot web actuator-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--一般通用配置-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
          </dependency>
      
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
          </dependency>
      </dependencies>
      
  3. 写yml

    • server:
        port: 7001
      
      
      
      eureka:
        instance:
          hostname: localhost #eureka服务端的实例名称
        client:
          #false表示不向注册中心注册自己。
          register-with-eureka: false
          #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
          fetch-registry: false
          service-url:
            #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      
      
  4. 主启动

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
      
      @EnableEurekaServer
      @SpringBootApplication
      public class CloudEurekaServer7001Application {
          public static void main(String[] args) {
              SpringApplication.run(CloudEurekaServer7001Application.class,args);
          }
      }
      
    • 一定要加@EnableEurekaServer,不然就完蛋了不要加@EnableEurekaClient

    • localhost:7001就可以看到下面这张图

      • image-20220118135105386

Eureka服务端和客户端依赖

  • 服务端

  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  • 客户端

  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  • 为什么Eureka不需要加版本号了呢?是不是因为由于springcloud里面已经限定好了呢?

Eureka 构建

  1. 创建项目

  2. 改pom

    • <!--eureka-client-->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      
  3. 写yml

    • eureka:
        client:
          #表示是否将自己注册进EurekaServer默认为true。
          register-with-eureka: true
          #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
          fetchRegistry: true
          service-url:
            defaultZone: http://localhost:7001/eureka
      
    • [fetch](javascript:😉: vt. 取来;接来;到达;吸引 | vi. 拿;

    • registry n. 注册;登记处;挂号处;船舶的国籍

  4. 主启动

  5. 自我保护机制

    • emergency! eureka may be incorrectly claiming instances are up when they’re not. renewals are lesser than threshold and hence the instances are not being expired just to be safe.
    • image-20220118140456302

Failed to bind properties under ‘eureka.client.service-url’ to java.util.Map<java.lang.String, java.lang.String>

image-20220118144439772

Eureka集群搭建

image-20220118155131581

image-20220118155906520

Eureka集群搭建

  1. 首先,就是先配置我们本地的hosts

    • C:\Windows\System32\drivers\etc

    • 然后加上

    • ####################SpringCloud2020.1.2##################
      127.0.0.1	eureka7001.com
      127.0.0.1	eureka7002.com
      
  2. 然后就是在创建一个Eureka服务端,端口7002

    • 写yml

      • # 集群配置
        eureka:
          instance:
            hostname: eureka7001.com #eureka服务端的实例名称
          client:
            register-with-eureka: false     #false表示不向注册中心注册自己。
            fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
            service-url:
              defaultZone: http://eureka7002.com:7002/eureka/
        
    • 7001那个也要改成这个

  3. 最后就是consumer还有payment的yml对应的Eureka要改一下

    • eureka:
        client:
          #表示是否将自己注册进EurekaServer默认为true。
          register-with-eureka: true
          #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
          fetchRegistry: true
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
      

支付模块集群搭建

  • 复制一份,然后改变一下端口,
  • 需要注意的是,“http://CLOUD-PAYMENT-SERVICE”
  • 然后就是改变一下baseUrl,因为…

没有负载均衡报错

解决方法

  • @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
  • 默认负载均衡规则:

    • 每个服务一次
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Jan 18 17:29:26 CST 2022
There was an unexpected error (type=Internal Server Error, status=500).
I/O error on GET request for "http://CLOUD-PAYMENT-SERVICE/payment/get/1": CLOUD-PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://CLOUD-PAYMENT-SERVICE/payment/get/1": CLOUD-PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:751)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:677)
	at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:318)
	at com.lin.controller.OrderController.getPayment(OrderController.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:196)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:162)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
	at java.net.Socket.connect(Socket.java:606)
	at java.net.Socket.connect(Socket.java:555)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
	at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
	at sun.net.www.http.HttpClient.New(HttpClient.java:339)
	at sun.net.www.http.HttpClient.New(HttpClient.java:357)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1226)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1162)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1056)
	at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:990)
	at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76)
	at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:742)
	... 57 more

Ribbon

  • Ribbon和Eureka整合后Consumer可以直接调用服务而**不用再关心地址和端口号,且该服务还有负载功能了。**O(∩_∩)O

actuator微服务信息完善

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
  instance:
    instance-id: payment8001
    prefer-ip-address: true

image-20220118192238452


效果图:

image-20220118192548390


服务发现Discovery

@Resource
private DiscoveryClient discoveryClient;

@GetMapping(value = "/discovery")
public Object discovery() {
    List<String> services = discoveryClient.getServices();
    for (String element : services) {
        System.out.println(element);
    }

    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    for (ServiceInstance element : instances) {
        System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
                           + element.getUri());
    }
    return this.discoveryClient;
}

image-20220118195002585


Eureka自我保护



image-20220118201520135



关闭保护模式

关闭自我保护模式后的效果

image-20220118211003860


noting: 我在7001进行了上面的测试,还没更改回去

设置客户端心跳发送间隔、服务端等待时间

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
  instance:
    instance-id: payment8001
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 10 # Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认为30秒)
    lease-expiration-duration-in-seconds: 20 # Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务

  • lease-renewal-interval-in-seconds: 10 # Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认为30秒)
  • lease-expiration-duration-in-seconds: 20 # Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务

07. Zookeeper学习

安装zookeeper

  • docker安装,简单快捷,哈哈哈哈

服务注册与发现

服务提供者

  1. 创建项目

    • 新建cloud-provider-payment8004
  2. 改pom

    • <dependencies>
          <!-- SpringBoot整合Web组件 -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!-- SpringBoot整合zookeeper客户端 -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. 写yml

    • #8004表示注册到zookeeper服务器的支付服务提供者端口号
      server:
        port: 8004
      
      
      #服务别名----注册zookeeper到注册中心名称
      spring:
        application:
          name: cloud-provider-payment
        cloud:
          zookeeper:
            connect-string: 47.98.251.199:2181
      
  4. 主启动

    • @EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
      @SpringBootApplication
      public class CloudProviderPayment8004Application {
          public static void main(String[] args) {
              SpringApplication.run(CloudProviderPayment8004Application.class,args);
          }
      }
      

zookeeper依赖报错

  • 我们引入的spring-cloud-starter-zookeeper-discovery依赖自带一个zookeeper3.5.3的,如果我们的依赖大于这个版本,我们在不改变依赖的前提下要怎么办呢?下面是解决方案。

    <!-- SpringBoot整合zookeeper客户端 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        <!--先排除自带的zookeeper3.5.3-->
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--添加zookeeper3.4.9版本-->
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.9</version>
    </dependency>
    
    • 我自己装的是3.5.9的zookeeper服务端,所以我应该不需要担心这个问题。

image-20220118233004605


进入zookeeper的dooker容器内部

  • docker exec -it d46a204f6e1c(this is id) bash

查看注册到zookeeper里面的服务

我的操作

服务节点

粗分:临时节点、持久节点

细分:带序号的临时节点、临时节点;带序号的持节节点、持节节点

然后就是我存在一个疑问

下面是你要的答案


集群搭建(自学)

  • 感觉没有必要重点去学,Nacos才是重点了,然后我学过两次了,哈哈哈,额。。。,现在感觉不知道学了啥
  • 所以一定要做笔记

自我感觉与迷惑


08. Consul学习

简介

能干什么

image-20220119122708120


安装

创建消费者

  1. 创建

  2. 改pom

    • <dependencies>
          <!--SpringCloud consul-server -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-consul-discovery</artifactId>
          </dependency>
          <!-- SpringBoot整合Web组件 -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--日常通用jar包配置-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. 写yml

    • ###consul服务端口号
      server:
        port: 80
      
      spring:
        application:
          name: consul-consumer-order
        ####consul注册中心地址
        cloud:
          consul:
            host: 47.98.251.199
            port: 8500
            discovery:
              #hostname: 127.0.0.1
              service-name: ${spring.application.name}
              heartbeat:
                enabled: true # 心跳发送
      
  4. 主启动

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      
      @EnableDiscoveryClient
      @SpringBootApplication
      public class PaymentMain8006 {
          public static void main(String[] args) {
              SpringApplication.run(PaymentMain8006.class,args);
          }
      }
      

CAP

CAP理论的核心

image-20220119134522984


Eureka:AP架构

AP架构
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP

image-20220119135041168


zookeeper/consul:CP架构

CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP

image-20220119135214292


Ribbon负载均衡

简介

能干什么

集中式LB

在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;

进程内LB

LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程消费方通过它来获取到服务提供方的地址

负载均衡+RestTemplate调用


架构说明

image-20220119143517878


使用

与RestTemplate配和使用

image-20220119144231891


image-20220119144305268




IRule:根据特定算法中从服务列表中选取一个要访问的服务

image-20220119144725149

image-20220119144732703

实战使用

1、配置

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule() {
        return new RandomRule();//定义为随机
    }
}

2、主启动

@RibbonClient(name = "cloud-payment-service",configuration = MySelfRule.class)//故意名字用小写
@EnableEurekaClient
@SpringBootApplication
public class CloudConsumerOrder80Application {
    public static void main(String[] args) {
        SpringApplication.run(CloudConsumerOrder80Application.class,args);
    }
}

3、restTemplate

@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  • 这个不要忘了啊
  • 测试了一下确实没问题

原理

源码解读

自己试着写一个本地负载均衡器试试

import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

public interface LoadBalancer {
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MyLoadBalancer implements LoadBalancer{

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement() {
        int current;
        int next;
        do {
            current = this.atomicInteger.get();
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*****next: "+next);
        return next;
    }

    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

OpenFeign学习

是什么

能干什么

Feign与OpenFeign的区别

image-20220119171610062

实战使用

  1. 创建项目

  2. 改pom

    • <dependencies>
          <!--openfeign-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
          <!--eureka client-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
          </dependency>
          <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
          <dependency>
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!--web-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--一般基础通用配置-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. 写yml

    • server:
        port: 80
      
      eureka:
        client:
          register-with-eureka: false
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      
  4. 主启动

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      
      @EnableFeignClients
      @SpringBootApplication
      public class OrderFeignMain80 {
          public static void main(String[] args) {
              SpringApplication.run(OrderFeignMain80.class,args);
          }
      }
      
    • @EnableFeignClients:这个可一定不要忘记了

  5. 业务类

    • 需要远程调用的接口

      • import com.lin.entities.CommonResult;
        import com.lin.entities.Payment;
        import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.stereotype.Component;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PathVariable;
        
        @Component
        @FeignClient("CLOUD-PAYMENT-SERVICE")
        public interface  PaymentFeignService {
            @GetMapping(value = "/payment/get/{id}")
            CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
        }
        
    • 本项目自己的控制层

      • @RestController
        public class OrderFeignController {
            @Resource
            private PaymentFeignService paymentFeignService;
        
            @GetMapping(value = "/consumer/payment/get/{id}")
            public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
                return paymentFeignService.getPaymentById(id);
            }
        }
        
      • 这个调用确实高,比我强上万倍

  6. 测试

    • 没问题,然后里面肯定是配了Ribbon,自己没有配就是默认规则。

image-20220119174839362

  • 我就很好奇,为什么之前学了一遍,然后又感觉自己等于没学呢?现在回味了一遍,还是感觉自己当初学了个寂寞,完全没有勾勒起之前的知识。

OpenFeign超时控制

  • OpenFeign默认等待1秒钟,超过后报错

image-20220119181813047


故意超时演示

  1. package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import com.atguigu.springcloud.service.PaymentService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @auther zzyy
     * @create 2020-01-27 21:17
     */
    @RestController
    @Slf4j
    public class PaymentController
    {
        @Value("${server.port}")
        private String serverPort;
    
        @Resource
        private PaymentService paymentService;
    
        @Resource
        private DiscoveryClient discoveryClient;
    
        @PostMapping(value = "/payment/create")
        public CommonResult create(@RequestBody Payment payment)
        {
            int result = paymentService.create(payment);
            log.info("*****插入操作返回结果:" + result);
    
            if(result > 0)
            {
                return new CommonResult(200,"插入成功,返回结果"+result+"\t 服务端口:"+serverPort,payment);
            }else{
                return new CommonResult(444,"插入失败",null);
            }
        }
    
        @GetMapping(value = "/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
        {
            Payment payment = paymentService.getPaymentById(id);
            log.info("*****查询结果:{}",payment);
            if (payment != null) {
                return new CommonResult(200,"查询成功"+"\t 服务端口:"+serverPort,payment);
            }else{
                return new CommonResult(444,"没有对应记录,查询ID: "+id,null);
            }
        }
    
        @GetMapping(value = "/payment/discovery")
        public Object discovery()
        {
            List<String> services = discoveryClient.getServices();
            for (String element : services) {
                System.out.println(element);
            }
    
            List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
            for (ServiceInstance element : instances) {
                System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
                        + element.getUri());
            }
            return this.discoveryClient;
        }
    
        @GetMapping(value = "/payment/lb")
        public String getPaymentLB()
        {
            System.out.println("*****lb from port: "+serverPort);
            return serverPort;
        }
    
        @GetMapping(value = "/payment/feign/timeout")
        public String paymentFeignTimeOut()
        {
            System.out.println("*****paymentFeignTimeOut from port: "+serverPort);
            //暂停几秒钟线程
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            return serverPort;
        }
    
    }
    
  2.  
    package com.atguigu.springcloud.service;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    /**
     * @auther zzyy
     * @create 2020-02-03 12:00
     */
    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface PaymentFeignService
    {
        @GetMapping(value = "/payment/get/{id}")
        CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
    
        @GetMapping(value = "/payment/feign/timeout")
        String paymentFeignTimeOut();
    }
    
  3.  
    package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import com.atguigu.springcloud.service.PaymentFeignService;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * @auther zzyy
     * @create 2020-02-03 14:10
     */
    @RestController
    public class OrderFeignController
    {
        @Resource
        private PaymentFeignService paymentFeignService;
    
        @GetMapping(value = "/consumer/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
        {
            return paymentFeignService.getPaymentById(id);
        }
    
        @GetMapping(value = "/consumer/payment/feign/timeout")
        public String paymentFeignTimeOut()
        {
            return paymentFeignService.paymentFeignTimeOut();
        }
    }
    

配置openfeign超时

image-20220119212745452


重头戏,配置


日志打印功能

是什么


配置

#指的是建立连接后从服务器读取到可用资源所用的时间


日志打印功能

是什么


配置
举报

相关推荐

0 条评论