服务生产与消费

在微服务架构中,服务提供者和服务消费者是两个核心概念,它们定义了微服务之间的关系和通信方式。

服务提供者是指提供某个具体功能或服务的微服务。它负责实现和暴露一组API接口,供其他微服务或客户端调用。服务提供者将自身的功能封装成服务,并通过网络暴露给外部。它可以是一个独立的微服务,也可以是由多个微服务组成的服务集群。

服务消费者是指依赖某个功能或服务的微服务或客户端。它需要通过调用服务提供者暴露的API接口来获取所需的功能或数据。服务消费者通过网络请求服务提供者,并处理返回的结果。消费者可以根据自己的需求,选择调用适当的服务提供者。

在微服务架构中,服务提供者和服务消费者之间的通信通常是通过远程调用来实现的。服务提供者通过公开API接口,提供了一组可以被调用的方法或服务。服务消费者可以通过网络请求这些API接口,以获取所需的功能或数据。

通过微服务的服务提供者-服务消费者模式,不同的微服务可以独立开发、部署和扩展,它们之间通过明确定义的接口进行通信,实现了解耦和灵活性。

这种模式还允许不同的团队独立地开发和维护各自的微服务,提高了开发效率和系统的可扩展性。

服务提供者

前面已经将用户服务注册到了eureka注册中心,但是还没有暴漏任何API给服务消费者调用。

模拟开发

Entity.User

注意导包的层级结构。

image-20230517142107357

package cn.yuchaoit.userservice.entity;

public class User {
    private int id;
    private String name;
    private int age;
    private String sex;

    public int getAge() {
        return age;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

UserController.java

image-20230517142003900

package cn.yuchaoit.userservice.controller;


import cn.yuchaoit.userservice.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController 
public class UserController {

    @GetMapping("/user")
    public String getUserService(){
        return "this is user-service";
    }

    @GetMapping("/user-nums")
    public Integer getUserNums(){
        return new Random().nextInt(100);
    }

    //{"id": 123, "name": "张三", "age": 20, "sex": "male"}
    @GetMapping("/user/{id}")
    public User getUserInfo(@PathVariable("id") int id){
        User user = new User();
        user.setId(id);
        user.setAge(20);
        user.setName("zhangsan");
        user.setSex("male");
        return user;
    }
}

application.yml

增加从环境变量中读取EUREKA_SERVEREUREKA_INSTANCE_HOSTNAME配置

server:
  port: 7000
eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_SERVER:http://${EUREKA_USER:admin}:${EUREKA_PASS:admin}@localhost:8761/eureka/}
  instance:
    instance-id: ${EUREKA_INSTANCE_HOSTNAME:${eureka.instance.hostname}:${server.port}}
    prefer-ip-address: true
    hostname: user-service
    lease-renewal-interval-in-seconds: 2

    lease-expiration-duration-in-seconds: 2
spring:
  application:
    name: user-service

重启测试API

http://127.0.0.1:7000/user

image-20230517142734681

http://127.0.0.1:7000/user/1

image-20230517142759767

k8s部署user-service

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  namespace: yuchao
spec:
  replicas: 1
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      imagePullSecrets:
      - name: registry-10.0.0.66
      containers:
        - name: user-service
          image: 10.0.0.66:5000/spring-cloud/user-service
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 7000
          resources:
            requests:
              memory: 400Mi
              cpu: 50m
            limits:
              memory: 2Gi
              cpu: 2000m
          env:
            - name: EUREKA_SERVER
              value: "http://admin:admin@eureka-cluster-0.eureka:8761/eureka/,http://admin:admin@eureka-cluster-1.eureka:8761/eureka/,http://admin:admin@eureka-cluster-2.eureka:8761/eureka/"
            - name: EUREKA_INSTANCE_HOSTNAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name

service

apiVersion: v1
kind: Service
metadata:
  name: user-service
  namespace: yuchao
spec:
  ports:
    - port: 7000
      protocol: TCP
      targetPort: 7000
  selector:
    app: user-service
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: user-service
  namespace: yuchao
spec:
  ingressClassName: nginx
  rules:
    - host: user-service.yuchaoit.cn
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: user-service
                port:
                  number: 7000

代码推送

git init
git remote add origin http://gitlab.yuchaoit.cn/spring-cloud/user-service.git
git add .
git commit -m "Initial commit"
git push -u origin master

image-20230517143416468

制作镜像

# mvn,jdk环境检查
[root@docker01 ~/springcloud/user-service]#tail -5 /etc/profile

export PATH=$PATH:/opt/apache-maven-3.3.9/bin
export JAVA_HOME=/opt/jdk8
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
You have new mail in /var/spool/mail/root




[root@docker01 /opt/jdk1.8.0_221]#ln -s /opt/jdk1.8.0_221/ /opt/jdk8
[root@docker01 /opt/jdk1.8.0_221]#source /etc/profile
[root@docker01 /opt/jdk1.8.0_221]#java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
[root@docker01 /opt/jdk1.8.0_221]#

[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:03 min
[INFO] Finished at: 2023-05-17T14:53:32+08:00
[INFO] Final Memory: 44M/210M
[INFO] ------------------------------------------------------------------------
You have new mail in /var/spool/mail/root
[root@docker01 ~/springcloud/user-service]#mvn clean package






# 2.打包镜像
[root@docker01 ~/springcloud/user-service]#
[root@docker01 ~/springcloud/user-service]#cat Dockerfile 
FROM openjdk:8-jdk-alpine
COPY target/user-service-0.0.1-SNAPSHOT.jar app.jar
ENV JAVA_OPTS=""
CMD [ "sh", "-c", "java $JAVA_OPTS -jar /app.jar" ]


[root@docker01 ~/springcloud/user-service]#docker build . -t 10.0.0.66:5000/spring-cloud/user-service 

# 3.推送镜像
[root@docker01 ~/springcloud/user-service]#docker push 10.0.0.66:5000/spring-cloud/user-service 
Using default tag: latest
The push refers to repository [10.0.0.66:5000/spring-cloud/user-service]
1850abd31d74: Pushed 
ceaf9e1ebef5: Mounted from spring-cloud/eureka-cluster 
9b9b7f3d56a0: Mounted from spring-cloud/eureka-cluster 
f1b5933fe4b5: Mounted from spring-cloud/eureka-cluster 
latest: digest: sha256:5760e10d74dfe43955ff63af43e5df3ee11c957f4b88d44b61baa1ab63866d9c size: 1159
You have mail in /var/spool/mail/root
[root@docker01 ~/springcloud/user-service]#

启动访问user-service

[root@k8s-master ~/springcloud]#kubectl apply -f .
ingress.networking.k8s.io/user-service created
service/user-service created
deployment.apps/user-service created


[root@k8s-master ~/springcloud]#kubectl -n yuchao get po
NAME                            READY   STATUS    RESTARTS       AGE
eladmin-api-7496b69c-dr9jk      1/1     Running   11 (47h ago)   5d22h
eladmin-web-7458474b64-mgrwp    1/1     Running   10 (25h ago)   27d
eureka-cluster-0                1/1     Running   0              20h
eureka-cluster-1                1/1     Running   0              20h
eureka-cluster-2                1/1     Running   0              20h
mysql-559d5fcc8b-vnpzf          1/1     Running   1 (25h ago)    2d21h
redis-7957d49f44-5mctq          1/1     Running   2 (25h ago)    2d21h
user-service-8544d8b7bb-kmgbx   1/1     Running   0              19s
yuchao-ngx                      1/1     Running   14 (25h ago)   40d
[root@k8s-master ~/springcloud]#

image-20230517145824218

k8s部署结束

image-20230517145846147

查看注册中心(重要)

[root@k8s-master ~/springcloud]#kubectl -n yuchao get po |grep user
user-service-5997c9d59f-ftc2c   1/1     Running   0              2m20s
user-service-5997c9d59f-rs2tx   1/1     Running   0              9s
user-service-5997c9d59f-wf2gw   1/1     Running   0              9s
user-service-5997c9d59f-xgzdb   1/1     Running   0              2m20s
[root@k8s-master ~/springcloud]#

# 服务节点,就是pod名字了

image-20230517160546188

每一个后端服务,只要启动后,会自动注册自己到注册中心,其他系统,只需要来Eureka里找节点就行。

以后直接通过USER_SERVICE就可以负载均衡,访问具体服务。

服务消费者

创建bill-service项目

新的模块初始化三部曲:

  • pom.xml
  • 启动类
  • 配置文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.yuchaoit</groupId>
    <artifactId>bill-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>bill-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

上述的包,maven本地都有了

application.yml

server:
  port: 7001
eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_SERVER:http://admin:admin@localhost:8761/eureka/}
  instance:
    instance-id: ${eureka.instance.hostname}:${server.port}
    prefer-ip-address: true
    hostname: ${INSTANCE_HOSTNAME:bill-service}
    #eureka客户端需要多长时间发送心跳给eureka服务器,表明他仍然或者,默认30秒
    lease-renewal-interval-in-seconds: 2
    #eureka服务器在接受到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除
    lease-expiration-duration-in-seconds: 2
spring:
  application:
    name: bill-service

BillController(微服务调用)

传统调用

package cn.yuchaoit.billservice.controller;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class BillController {

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

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/bill/user")
    public String getUserInfo(){
        return restTemplate.getForObject("http://localhost:7000/user", String.class);
    }
}

微服务调用

package cn.yuchaoit.billservice.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class BillController {

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

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/bill/user")
    public String getUserInfo(){
        return restTemplate.getForObject("http://user-service/user", String.class);
    }
}

BillServiceApplication启动类型

package cn.yuchaoit.billservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class BillServiceApplication {

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

}

启动bill账单服务

账单是和用户关联的,需要去调取用户信息

  main] c.y.billservice.BillServiceApplication   : No active profile set, falling back to default profiles: default
2023-05-17 16:35:13.766  INFO 12532 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=8459d36c-3fcb-3e53-bdc9-3512c96e62ff
2023-05-17 16:35:13.918  INFO 12532 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 7001 (http)

image-20230517163719135

服务端口7001,访问试试

image-20230517163919727

小结

完成bill-service > user-service的调用,这里只是为了理解服务调用的概念,两套系统通过远程访问,如restfulAPI

当然在代码层面,微服务框架,本身还存在负载均衡算法等知识点,这些不属于运维层面理解。

image-20230517164128554

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2024-03-31 19:43:22

results matching ""

    No results matching ""