-
前端和後端緊密耦合——實際上它不能在沒有後端的情況下處理應用
-
前端和後端必須一致擴充套件——如果沒有足夠的後端,你可能會淹沒在流量中
-
如果後端不可用,則無法處理傳入的事務。
-
如果後端不可用,則佇列充當緩衝區
-
如果前端產生的訊息多於後端可以處理的訊息,則這些訊息將緩衝在佇列中
-
你可以獨立於前端擴充套件後端——即你可以擁有數百個前端服務和後端的單個實體
-
一個購買物品的主頁
-
管理面板,你可以在其中檢查佇列中的訊息數
-
一個 /health 端點,用於在應用程式準備好接收流量時發出訊號
-
一個 /submit 端點,從表單接收提交併在佇列中建立訊息
-
一個 /metrics 端點,用於公開佇列中待處理訊息的數量(稍後將詳細介紹)
@Component
public class QueueService implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(QueueService.class);
@Autowired
private JmsTemplate jmsTemplate;
public void send(String destination, String message) {
LOGGER.info("sending message='{}' to destination='{}'", message, destination);
jmsTemplate.convertAndSend(destination, message);
}
@Override
public void onMessage(Message message) {
if (message instanceof ActiveMQTextMessage) {
ActiveMQTextMessage textMessage = (ActiveMQTextMessage) message;
try {
LOGGER.info("Processing task " textMessage.getText());
Thread.sleep(5000);
LOGGER.info("Completed task " textMessage.getText());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
} else {
LOGGER.error("Message is not a text message " message.toString());
}
}
}
@SpringBootApplication
@EnableJms
public class SpringBootApplication implements JmsListenerConfigurer {
@Autowired
private QueueService queueService;
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myId");
endpoint.setDestination("queueName");
endpoint.setMessageListener(queueService);
registrar.registerEndpoint(endpoint);
}
}
minikube start \
--memory 8096 \
--extra-config=controller-manager.horizontal-pod-autoscaler-upscale-delay=1m \
--extra-config=controller-manager.horizontal-pod-autoscaler-downscale-delay=2m \
--extra-config=controller-manager.horizontal-pod-autoscaler-sync-period=10s
minikube docker-env
docker build -t spring-k8s-hp0a .
docker images |grep spring
-
呈現前端的Spring Boot應用程式
-
ActiveMQ作為訊息代理
-
處理事務的Spring Boot後端
-
Deployment物件,描述部署的容器及其配置
-
一個Service物件,充當Deployment部署建立的應用程式的所有實體的負載均衡器
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: queue
spec:
replicas: 1
template:
metadata:
labels:
app: queue
spec:
containers:
- name: web
image: webcenter/activemq:5.14.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 61616
resources:
limits:
memory: 512Mi
-
你從名為webcenter / activemq的官方倉庫中請求了一個activemq容器
-
容器在埠61616上公開訊息代理
-
為容器分配了512MB的記憶體
-
你要求提供單個副本 – 你的應用程式的單個實體
apiVersion: v1
kind: Service
metadata:
name: queue
spec:
ports:
- port: 61616
targetPort: 61616
selector:
app: queue
-
你建立了一個公開埠61616的負載均衡器
-
傳入流量分發到所有具有app:queue型別標簽的Pod(請參閱上面的部署)
-
targetPort是Pod暴露的埠
kubectl create -f activemq-deployment.yaml
kubectl create -f activemq-service.yaml
kubectl get pods -l=app=queue
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: spring-boot-hpa
imagePullPolicy: IfNotPresent
env:
- name: ACTIVEMQ_BROKER_URL
value: "tcp://queue:61616"
- name: STORE_ENABLED
value: "true"
- name: WORKER_ENABLED
value: "false"
ports:
- containerPort: 8080
livenessProbe:
initialDelaySeconds: 5
periodSeconds: 5
httpGet:
path: /health
port: 8080
resources:
limits:
memory: 512Mi
-
有一個section可以註入環境變數
-
還有Liveness探針,可以告訴你應用程式何時可以接受流量
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- nodePort: 32000
port: 80
targetPort: 8080
selector:
app: frontend
type: NodePort
kubectl create -f fe-deployment.yaml
kubectl create -f fe-service.yaml
kubectl get pods -l=app=frontend
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
template:
metadata:
labels:
app: backend
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: backend
image: spring-boot-hpa
imagePullPolicy: IfNotPresent
env:
- name: ACTIVEMQ_BROKER_URL
value: "tcp://queue:61616"
- name: STORE_ENABLED
value: "false"
- name: WORKER_ENABLED
value: "true"
ports:
- containerPort: 8080
livenessProbe:
initialDelaySeconds: 5
periodSeconds: 5
httpGet:
path: /health
port: 8080
resources:
limits:
memory: 512Mi
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
ports:
- nodePort: 31000
port: 80
targetPort: 8080
selector:
app: backend
type: NodePort
kubectl create -f backend-deployment.yaml
kubectl create -f backend-service.yaml
kubectl get pods -l=app=backend
minikube service backend
minikube service frontend
-
你可以手動放大和縮小
-
你可以建立自動縮放規則以自動向上或向下擴充套件
kubectl scale --replicas=5 deployment/backend
kubectl get pods
kubectl scale --replicas=1 deployment/backend
# HELP messages Number of messages in the queue
# TYPE messages gauge
messages 0
cd spring-boot-k8s-hpa/monitoring
kubectl create -f ./metrics-server
kubectl create -f ./namespaces.yaml
kubectl create -f ./prometheus
kubectl create -f ./custom-metrics-api
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq .
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/messages" | jq .
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: spring-boot-hpa
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: backend
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metricName: messages
targetAverageValue: 10
-
Kubernetes監視scaleTargetRef中指定的部署。在這種情況下,它是工人。
-
你正在使用messages指標來擴充套件你的Pod。當佇列中有超過十條訊息時,Kubernetes將觸發自動擴充套件。
-
至少,部署應該有兩個Pod。10個Pod是上限。
kubectl create -f hpa.yaml
kubectl describe hpa
kubectl describe hpa
MAX(CURRENT_REPLICAS_LENGTH * 2, 4)
-
https://github.com/learnk8s/spring-boot-k8s-hpa
-
https://github.com/learnk8s/spring-boot-k8s-hpa/blob/master/src/main/java/com/learnk8s/app/queue/QueueService.java
-
https://kubernetes.io/docs/tasks/tools/
-
https://learnk8s.io/blog/installing-docker-and-kubernetes-on-windows
-
https://docs.docker.com/install/
-
https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#deployment